<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type='text/xsl' href='http://machaira.spaces.live.com/mmm2008-05-17_13.22/rsspretty.aspx?rssquery=en-US;http%3a%2f%2fmachaira.spaces.live.com%2fcategory%2fProgramming%2ffeed.rss' version='1.0'?><rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:msn="http://schemas.microsoft.com/msn/spaces/2005/rss" xmlns:live="http://schemas.microsoft.com/live/spaces/2006/rss" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:cf="http://www.microsoft.com/schemas/rss/core/2005" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Machaira's Space: Programming</title><description /><link>http://machaira.spaces.live.com/?_c11_BlogPart_BlogPart=blogview&amp;_c=BlogPart&amp;partqs=catProgramming</link><language>en-US</language><pubDate>Fri, 18 Jul 2008 07:30:12 GMT</pubDate><lastBuildDate>Fri, 18 Jul 2008 07:30:12 GMT</lastBuildDate><generator>Microsoft Spaces v1.1</generator><docs>http://www.rssboard.org/rss-specification</docs><ttl>60</ttl><cf:parentRSS>http://machaira.spaces.live.com/blog/feed.rss</cf:parentRSS><live:type>blogcategory</live:type><live:identity><live:id>-4134251031648887394</live:id><live:alias>machaira</live:alias></live:identity><cf:listinfo><cf:group ns="http://schemas.microsoft.com/live/spaces/2006/rss" element="typelabel" label="Type" /><cf:group ns="http://schemas.microsoft.com/live/spaces/2006/rss" element="tag" label="Tag" /><cf:group element="category" label="Category" /><cf:sort element="pubDate" label="Date" data-type="date" default="true" /><cf:sort element="title" label="Title" data-type="string" /><cf:sort ns="http://purl.org/rss/1.0/modules/slash/" element="comments" label="Comments" data-type="number" /></cf:listinfo><item><title>HLSL Syntax Highlighting</title><link>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!490.entry</link><description>&lt;p&gt;From &lt;a href="http://forums.xna.com/thread/41779.aspx" target="_blank"&gt;this post&lt;/a&gt; in the Creators Club forums: &lt;p&gt;  &lt;blockquote&gt; &lt;p&gt;InteliShade is an add-in for Visual Studio 2005 non-Express SKUs (Add-ins are not allowed in Express) that enabled syntax highlighting in your HLSL (.fx) files. New features in Beta 1.2 also include auto-completion (hit Ctrl-Space to open intelisense) and tooltip styled documentation (hovering over texture tells you what kind of object it is). All known performance issues have been taken care of. &lt;p&gt;So try it out and suggest some ideas and opinions on how to improve it! &lt;p&gt;&lt;a href="http://intelishade.net/files/folders/beta_releases/entry41.aspx"&gt;http://intelishade.net/files/folders/beta_releases/entry41.aspx&lt;/a&gt;&lt;/blockquote&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-4134251031648887394&amp;page=RSS%3a+HLSL+Syntax+Highlighting&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=machaira.spaces.live.com&amp;amp;GT1=machaira"&gt;</description><comments>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!490.entry#comment</comments><guid isPermaLink="true">http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!490.entry</guid><pubDate>Wed, 16 Jan 2008 12:39:24 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://machaira.spaces.live.com/blog/cns!C6A0309746469D9E!490/comments/feed.rss</wfw:commentRss><wfw:comment>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!490.entry#comment</wfw:comment><dcterms:modified>2008-01-16T12:39:24Z</dcterms:modified></item><item><title>Breakout level class</title><link>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!488.entry</link><description>&lt;p&gt;Threw this code together in about 5 minutes in response to a question on gamedev.net and figured I'd throw it out here for anyone that's interested. I make no claims about it being the ideal way to do a Breakout level. :) &lt;p&gt; &lt;pre&gt;    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; Brick
    {
        &lt;span&gt;private&lt;/span&gt; BoundingBox _box;
        &lt;span&gt;private&lt;/span&gt; Vector2 _location;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;bool&lt;/span&gt; _alive;

        &lt;span&gt;public&lt;/span&gt; Brick(Vector2 location)
        {
            _location = location;
            _box = &lt;span&gt;new&lt;/span&gt; BoundingBox(&lt;span&gt;new&lt;/span&gt; Vector3(location.X, location.Y, 0), &lt;span&gt;new&lt;/span&gt; Vector3(location.X * Level.BrickWidth, location.Y * Level.BrickHeight, 0));
            _alive = &lt;span&gt;true&lt;/span&gt;;
        }

        &lt;span&gt;public&lt;/span&gt; Vector2 Location
        {
            get { &lt;span&gt;return&lt;/span&gt; _location; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;bool&lt;/span&gt; Alive
        {
            get { &lt;span&gt;return&lt;/span&gt; _alive; }
        }

        &lt;span&gt;public&lt;/span&gt; BoundingBox Box
        {
            get { &lt;span&gt;return&lt;/span&gt; _box; }
        }
            
        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; Kill()
        {
            _alive = &lt;span&gt;false&lt;/span&gt;;
        }
    }

    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; Level
    {
        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;const&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; BrickWidth = 32;
        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;const&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; BrickHeight = 8;

        &lt;span&gt;private&lt;/span&gt; List&amp;lt;Brick&amp;gt; _bricks;

        &lt;span&gt;public&lt;/span&gt; Level(&lt;span&gt;int&lt;/span&gt; rows, &lt;span&gt;int&lt;/span&gt; cols)
        {
            _bricks = &lt;span&gt;new&lt;/span&gt; List&amp;lt;Brick&amp;gt;();

            Brick brick;

            &lt;span&gt;for&lt;/span&gt; (&lt;span&gt;int&lt;/span&gt; x = 0; x&amp;lt;cols;x++)
            {
                &lt;span&gt;for&lt;/span&gt; (&lt;span&gt;int&lt;/span&gt; y = 0;y&amp;lt;rows;y++)
                {
                    brick = &lt;span&gt;new&lt;/span&gt; Brick(&lt;span&gt;new&lt;/span&gt; Vector2(x * BrickWidth, y * BrickHeight));
                    _bricks.Add(brick);
                }
            }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; LevelUp(&lt;span&gt;int&lt;/span&gt; rows, &lt;span&gt;int&lt;/span&gt; cols)
        {
            _bricks.Clear();

            Brick brick;

            &lt;span&gt;for&lt;/span&gt; (&lt;span&gt;int&lt;/span&gt; x = 0; x &amp;lt; cols; x++)
            {
                &lt;span&gt;for&lt;/span&gt; (&lt;span&gt;int&lt;/span&gt; y = 0; y &amp;lt; rows; y++)
                {
                    brick = &lt;span&gt;new&lt;/span&gt; Brick(&lt;span&gt;new&lt;/span&gt; Vector2(x * BrickWidth, y * BrickHeight));
                    _bricks.Add(brick);
                }
            }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;bool&lt;/span&gt; CheckForCollision(BoundingBox ball)
        {
            BoundingBox brick;
            Vector2 location;
            &lt;span&gt;bool&lt;/span&gt; ret = &lt;span&gt;false&lt;/span&gt;;

            &lt;span&gt;for&lt;/span&gt; (&lt;span&gt;int&lt;/span&gt; i = 0; i &amp;lt; _bricks.Count; i++)
            {
                &lt;span&gt;if&lt;/span&gt; (_bricks[i].Alive)
                {
                    ret = ball.Intersects(_bricks[i].Box);

                    &lt;span&gt;if&lt;/span&gt; (ret)
                    {
                        _bricks[i].Kill();
                        &lt;span&gt;break&lt;/span&gt;;
                    }
                }
            }

            &lt;span&gt;return&lt;/span&gt; ret;
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; Render()
        {
            &lt;span&gt;for&lt;/span&gt; (&lt;span&gt;int&lt;/span&gt; i = 0; i &amp;lt; _bricks.Count; i++)
            {
                &lt;span&gt;if&lt;/span&gt; (_bricks[i].Alive)
                {
                    &lt;span&gt;//render&lt;/span&gt;
                }
            }

        }
    }
&lt;/pre&gt;
&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-4134251031648887394&amp;page=RSS%3a+Breakout+level+class&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=machaira.spaces.live.com&amp;amp;GT1=machaira"&gt;</description><comments>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!488.entry#comment</comments><guid isPermaLink="true">http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!488.entry</guid><pubDate>Thu, 10 Jan 2008 20:55:33 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://machaira.spaces.live.com/blog/cns!C6A0309746469D9E!488/comments/feed.rss</wfw:commentRss><wfw:comment>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!488.entry#comment</wfw:comment><dcterms:modified>2008-01-10T20:55:33Z</dcterms:modified></item><item><title>RPG Game Development - Part 6</title><link>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!478.entry</link><description>&lt;p&gt;A mainstay of RPGs are quests. Usually there's at least one main quest and often several side quests that may or may not be necessary. The main quest may involve many people, places, and/or items. We need an easy way to track all of this so the player knows what he's already done and what needs to be done next. We'll implement a system that should be able to handle most questing needs of a developer. &lt;p&gt;  &lt;p&gt;A quest is made up of one or more steps, so we'll start off with a class to encapsulate the data for a step: &lt;p&gt; &lt;pre&gt;    [Serializable]
    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; QuestStep 
    {
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; _stepName;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _giveItemID;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _getItemID;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _stepEntityID;
        &lt;span&gt;private&lt;/span&gt; InteractionType _stepInteractionType;

        &lt;span&gt;// ID of conversation script which is started when StepEntity is interacted with&lt;/span&gt;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _conversationID;

        &lt;span&gt;// array of IDs of subquests&lt;/span&gt;
        &lt;span&gt;private&lt;/span&gt; List&amp;lt;&lt;span&gt;int&lt;/span&gt;&amp;gt; _subQuestIDs;

        &lt;span&gt;private&lt;/span&gt; List&amp;lt;Item&amp;gt; _requiredItems;
        
        &lt;span&gt;// required level to start the step, each step may have a different level&lt;/span&gt;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;byte&lt;/span&gt; _minimumLevel;

        &lt;span&gt;// number of minutes the step can take&lt;/span&gt;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;long&lt;/span&gt; _timeLimit;

        &lt;span&gt;private&lt;/span&gt; QuestRewardType _rewardItemType;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _rewardItemID;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _rewardMoneyAmount;
        
        &lt;span&gt;public&lt;/span&gt; QuestStep() 
        {
            
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; StepName
        {
            get {&lt;span&gt;return&lt;/span&gt; _stepName;}
            set {&lt;span&gt;if&lt;/span&gt; (!&lt;span&gt;string&lt;/span&gt;.IsNullOrEmpty(&lt;span&gt;value&lt;/span&gt;)) _stepName=&lt;span&gt;value&lt;/span&gt;;}
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; GiveItemID
        {
            get { &lt;span&gt;return&lt;/span&gt; _giveItemID; }
            set { &lt;span&gt;if&lt;/span&gt; (&lt;span&gt;value&lt;/span&gt; &amp;gt; 0) _giveItemID = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; GetItemID
        {
            get { &lt;span&gt;return&lt;/span&gt; _getItemID; }
            set { &lt;span&gt;if&lt;/span&gt; (&lt;span&gt;value&lt;/span&gt; &amp;gt; 0) _getItemID = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; StepEntityID
        {
            get { &lt;span&gt;return&lt;/span&gt; _stepEntityID; }
            set { &lt;span&gt;if&lt;/span&gt; (&lt;span&gt;value&lt;/span&gt; &amp;gt; 0) _stepEntityID = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; InteractionType StepInteractionType
        {
            get { &lt;span&gt;return&lt;/span&gt; _stepInteractionType; }
            set { _stepInteractionType = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; ConversationID
        {
            get { &lt;span&gt;return&lt;/span&gt; _conversationID; }
            set { &lt;span&gt;if&lt;/span&gt; (&lt;span&gt;value&lt;/span&gt; &amp;gt; 0) _conversationID = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; AddSubQuest(&lt;span&gt;int&lt;/span&gt; ID)
        {
            &lt;span&gt;if&lt;/span&gt; (_subQuestIDs == &lt;span&gt;null&lt;/span&gt;)
                _subQuestIDs = &lt;span&gt;new&lt;/span&gt; List&amp;lt;&lt;span&gt;int&lt;/span&gt;&amp;gt;();

            _subQuestIDs.Add(ID);
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; InsertSubQuestID(&lt;span&gt;int&lt;/span&gt; index, &lt;span&gt;int&lt;/span&gt; ID)
        {
            &lt;span&gt;if&lt;/span&gt; (_subQuestIDs == &lt;span&gt;null&lt;/span&gt;)
                _subQuestIDs = &lt;span&gt;new&lt;/span&gt; List&amp;lt;&lt;span&gt;int&lt;/span&gt;&amp;gt;();

            &lt;span&gt;if&lt;/span&gt; (index &amp;lt;= _subQuestIDs.Count - 1)
                _subQuestIDs.Insert(index, ID);
            &lt;span&gt;else&lt;/span&gt;
                &lt;span&gt;throw&lt;/span&gt; &lt;span&gt;new&lt;/span&gt; IndexOutOfRangeException(&lt;span&gt;&amp;quot;Number of sub-quests is less than the index passed to the InsertSubQuestID method&amp;quot;&lt;/span&gt;);
        }

        &lt;span&gt;public&lt;/span&gt; List&amp;lt;&lt;span&gt;int&lt;/span&gt;&amp;gt; SubQuestIDs
        {
            get { &lt;span&gt;return&lt;/span&gt; _subQuestIDs; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; RemoveSubQuestIDByIndex(&lt;span&gt;int&lt;/span&gt; index)
        {
            _subQuestIDs.RemoveAt(index);
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; RemoveSubQuestIDByID(&lt;span&gt;int&lt;/span&gt; ID)
        {
            _subQuestIDs.Remove(ID);
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; AddRequiredItem(Item item)
        {
            &lt;span&gt;if&lt;/span&gt; (_requiredItems == &lt;span&gt;null&lt;/span&gt;)
                _requiredItems = &lt;span&gt;new&lt;/span&gt; List&amp;lt;Item&amp;gt;();

            _requiredItems.Add(item);
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; RemoveRequiredItemByIndex(&lt;span&gt;int&lt;/span&gt; index)
        {
            _requiredItems.RemoveAt(index);
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; RemoveSubQuestIDByItem(Item item)
        {
            _requiredItems.Remove(item);
        }

        &lt;span&gt;public&lt;/span&gt; List&amp;lt;Item&amp;gt; RequiredItems
        {
            get { &lt;span&gt;return&lt;/span&gt; _requiredItems; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;byte&lt;/span&gt; MinimumLevel
        {
            get { &lt;span&gt;return&lt;/span&gt; _minimumLevel; }
            set { &lt;span&gt;if&lt;/span&gt; (&lt;span&gt;value&lt;/span&gt; &amp;gt; 0) _minimumLevel = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;long&lt;/span&gt; TimeLimit
        {
            get { &lt;span&gt;return&lt;/span&gt; _timeLimit; }
            set { &lt;span&gt;if&lt;/span&gt; (&lt;span&gt;value&lt;/span&gt; &amp;gt; 0) _timeLimit = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; QuestRewardType RewardItemType
        {
            get { &lt;span&gt;return&lt;/span&gt; _rewardItemType; }
            set { _rewardItemType = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; RewardItemID
        {
            get { &lt;span&gt;return&lt;/span&gt; _rewardItemID; }
            set { &lt;span&gt;if&lt;/span&gt; (&lt;span&gt;value&lt;/span&gt; &amp;gt; -1) _rewardItemID = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; RewardMoneyAmount
        {
            get { &lt;span&gt;return&lt;/span&gt; _rewardMoneyAmount; }
            set { &lt;span&gt;if&lt;/span&gt; (&lt;span&gt;value&lt;/span&gt; &amp;gt; 0) _rewardMoneyAmount = &lt;span&gt;value&lt;/span&gt;; }
        }
    }
&lt;/pre&gt;




&lt;p&gt; The InteractionType enum contains only two items at this point:
&lt;p&gt; &lt;pre&gt;    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;enum&lt;/span&gt; InteractionType 
    {
        Talk,
        Kill
    }&lt;/pre&gt;
&lt;p&gt;


&lt;p&gt;You could add some other values here - Steal, Subdue, Follow, etc. but for our purposes these two will do.
&lt;p&gt; 
&lt;p&gt;The QuestRewardType enum has the following in it:
&lt;p&gt; &lt;pre&gt;    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;enum&lt;/span&gt; QuestRewardType 
    {
        Armor,
        Item,
        Money,
        Spell,
        Weapon
    }
&lt;/pre&gt;


&lt;p&gt; 
&lt;p&gt;You might be asking what the difference between _giveItemID and _rewardItemID are. That's a very good question. Imagine a step where an NPC says &amp;quot;Give this ring to &amp;lt;some other NPC&amp;gt; and here's &amp;lt;some random item&amp;gt; for your trouble&amp;quot;. The first item is the _giveItemID and the second is the _rewardItemID. In the case of money as a reward the _rewardItemID is ignored and the _rewardMoneyAmount is used instead.
&lt;p&gt; 
&lt;p&gt;Here's the main Quest class:
&lt;p&gt; &lt;pre&gt;    [Serializable]
    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; Quest 
    {
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _id;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; _name;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; _description;
        &lt;span&gt;private&lt;/span&gt; QuestType _type;
        &lt;span&gt;private&lt;/span&gt; QuestRewardType _rewardType;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _rewardItemID;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _rewardMoneyAmount;
        &lt;span&gt;private&lt;/span&gt; List&amp;lt;&lt;span&gt;int&lt;/span&gt;&amp;gt; _requiredClasses;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _requiredLevel;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;bool&lt;/span&gt; _isMultipleAllowed;

        &lt;span&gt;// 0 means no limit&lt;/span&gt;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;long&lt;/span&gt; _timeBetweenQuests;

        &lt;span&gt;// total time in which quest must be completed, 0 for none&lt;/span&gt;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;long&lt;/span&gt; _timeLimit;

        &lt;span&gt;// is the reward known by the player when accepting the quest&lt;/span&gt;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;bool&lt;/span&gt; _isRewardShown;

        &lt;span&gt;private&lt;/span&gt; List&amp;lt;FactionAdjust&amp;gt; _factions;

        &lt;span&gt;private&lt;/span&gt; List&amp;lt;QuestStep&amp;gt; _steps = &lt;span&gt;new&lt;/span&gt; List&amp;lt;QuestStep&amp;gt;();
        
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; _fileName;
        
        &lt;span&gt;public&lt;/span&gt; Quest() 
        {

        }
        
        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; ID 
        {
            get { &lt;span&gt;return&lt;/span&gt; _id; }
            set { &lt;span&gt;if&lt;/span&gt; (&lt;span&gt;value&lt;/span&gt; &amp;gt; 0) _id = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; Name
        {
            get { &lt;span&gt;return&lt;/span&gt; _name; }
            set { &lt;span&gt;if&lt;/span&gt; (!&lt;span&gt;string&lt;/span&gt;.IsNullOrEmpty(&lt;span&gt;value&lt;/span&gt;)) _name = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; Description
        {
            get { &lt;span&gt;return&lt;/span&gt; _description; }
            set { _description = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; QuestType Type
        {
            get { &lt;span&gt;return&lt;/span&gt; _type; }
            set { _type = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; QuestRewardType RewardType
        {
            get { &lt;span&gt;return&lt;/span&gt; _rewardType; }
            set { _rewardType = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; RewardItemID
        {
            get { &lt;span&gt;return&lt;/span&gt; _rewardItemID; }
            set { _rewardItemID = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; List&amp;lt;&lt;span&gt;int&lt;/span&gt;&amp;gt; RequiredClasses
        {
            get { &lt;span&gt;return&lt;/span&gt; _requiredClass; }
            set { _requiredClass = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; RequiredLevel
        {
            get { &lt;span&gt;return&lt;/span&gt; _requiredLevel; }
            set { &lt;span&gt;if&lt;/span&gt; (&lt;span&gt;value&lt;/span&gt; &amp;gt; 0) _requiredLevel = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;bool&lt;/span&gt; MultipleAllowed
        {
            get { &lt;span&gt;return&lt;/span&gt; _isMultipleAllowed; }
            set { _isMultipleAllowed = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;long&lt;/span&gt; TimeBetweenQuests
        {
            get { &lt;span&gt;return&lt;/span&gt; _timeBetweenQuests; }
            set { &lt;span&gt;if&lt;/span&gt; (&lt;span&gt;value&lt;/span&gt; &amp;gt; -1) _timeBetweenQuests = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;long&lt;/span&gt; TimeLimit
        {
            get { &lt;span&gt;return&lt;/span&gt; _timeLimit; }
            set { &lt;span&gt;if&lt;/span&gt; (&lt;span&gt;value&lt;/span&gt; &amp;gt; -1) _timeLimit = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;bool&lt;/span&gt; RewardShown
        {
            get { &lt;span&gt;return&lt;/span&gt; _isRewardShown; }
            set { _isRewardShown = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; List&amp;lt;FactionAdjust&amp;gt; Factions
        {
            get { &lt;span&gt;return&lt;/span&gt; _factions; }
            set { _factions = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; List&amp;lt;QuestStep&amp;gt; Steps
        {
            get { &lt;span&gt;return&lt;/span&gt; _steps; }
            set { _steps = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; FileName
        {
            get { &lt;span&gt;return&lt;/span&gt; _fileName; }
            set { _fileName = &lt;span&gt;value&lt;/span&gt;; }
        }
    }
&lt;/pre&gt;


&lt;p&gt; 
&lt;p&gt; A quest can be one of the following types:
&lt;p&gt; &lt;pre&gt;    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;enum&lt;/span&gt; QuestType 
    {
        FedEx,
        Item,
        Kill,
        Rescue
    }&lt;/pre&gt;
&lt;p&gt;


&lt;p&gt;A FedEx quest is a delivery of some item from one NPC to another. The Item value means the player has to find some item and return it to the NPC that originates the quest. 
&lt;p&gt; 
&lt;p&gt;Factions are something that allow you to determine how a group of people, guards for instance, react to the player. Most MMORPGs have quests that allow the player to modify their faction value for certain groups. This can be used in single-player RPGs as well. The FactionAdjust class is simply an ID and Value pair:
&lt;p&gt; &lt;pre&gt;    [Serializable]
    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; FactionAdjust
    {
        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; ID;
        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; Value;
    }
&lt;/pre&gt;


&lt;p&gt; 
&lt;p&gt;In your data somewhere you'd have a list of faction types (Merchant, Guard, specific monster type). Value can be positive or negative and a quest could affect one faction positively and lower another. For instance, a quest to kill 10 goblins might positively affect the people in an area where the goblins are a problem but would obviously affect the goblin nation negatively. If you allow players to play as a race that is normally not reacted to hostilely by goblins, this allows you to make them so if the player goes on a goblin killing spree.
&lt;p&gt; 
&lt;p&gt;One area you might want to change, depending on how you work your classes, is the _requiredLevel member. The way the class is implemented, all classes that are allowed have to be the same. You couldn't have a quest where a warrior has to be level 5 and a mage has to be level 10. That's easily fixed by implementing a list of ID and value pairs, like the FactionAdjust above, and replacing the _requiredClasses and _requiredLevel members with it.
&lt;p&gt; 
&lt;p&gt;So how do we assign a question to the player? We add an instance of the AssignedQuest class to the player's Entity object:
&lt;p&gt; &lt;pre&gt;    &lt;span&gt;// An array of this goes in the Entity class&lt;/span&gt;
    [Serializable]
    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; AssignedQuest
    {
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;long&lt;/span&gt; _questID;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _curStep;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;long&lt;/span&gt; _timeStepStarted;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;long&lt;/span&gt; _timeStepFinished;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;long&lt;/span&gt; _timeQuestStarted;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;long&lt;/span&gt; _timeQuestFinished;
        
    }&lt;/pre&gt;&lt;pre&gt; &lt;/pre&gt;
&lt;p&gt;We'll need a manager and service to allow code to get information about quests. Here they are:
&lt;p&gt; &lt;pre&gt;    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; QuestManager
    {
        &lt;span&gt;private&lt;/span&gt; List&amp;lt;Quest&amp;gt; _quests;

        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;static&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _numQuests = 0;

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;static&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; NumQuests
        {
            get { &lt;span&gt;return&lt;/span&gt; _numQuests; }
        }

        &lt;span&gt;public&lt;/span&gt; QuestManager(&lt;span&gt;string&lt;/span&gt; filename)
        {
            &lt;span&gt;if&lt;/span&gt; (File.Exists(filename))
            {
                XmlSerializer serializer = &lt;span&gt;new&lt;/span&gt; XmlSerializer(&lt;span&gt;typeof&lt;/span&gt;(List&amp;lt;Quest&amp;gt;));

                FileStream fs = &lt;span&gt;new&lt;/span&gt; FileStream(filename, FileMode.Open);

                _quests = (List&amp;lt;Quest&amp;gt;)serializer.Deserialize(fs);

                _numQuests = _quests.Count;
            }
        }

        &lt;span&gt;public&lt;/span&gt; Quest GetQuest(&lt;span&gt;int&lt;/span&gt; id)
        {
            &lt;span&gt;foreach&lt;/span&gt; (Quest quest &lt;span&gt;in&lt;/span&gt; _quests)
            {
                &lt;span&gt;if&lt;/span&gt; (quest.ID == id)
                    &lt;span&gt;return&lt;/span&gt; quest;
                &lt;span&gt;break&lt;/span&gt;;
            }

            &lt;span&gt;return&lt;/span&gt; &lt;span&gt;null&lt;/span&gt;;
        }
    }&lt;/pre&gt;&lt;pre&gt; &lt;/pre&gt;&lt;pre&gt;    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;interface&lt;/span&gt; IQuestManagerService
    {
        Quest GetQuest(&lt;span&gt;int&lt;/span&gt; id);
    }
&lt;/pre&gt;
&lt;p&gt;


&lt;p&gt;I should probably mention that the Starter Kit that will eventually be developed will contain an interface for creating quests (as it will for all the other objects) so don't feel you need to start working on one (unless you really want to, of course). :)
&lt;p&gt; 
&lt;p&gt;&lt;a href="http://www.machxgames.com/forum/default.aspx?g=posts&amp;amp;t=37" target="_blank"&gt;Here's&lt;/a&gt; the usual link to the forums for discussion. I'm sure there's areas for improvement here so feel free to let me know. Hopefully this post will be useful in helping you to design your quest system if you don't want to wait for the release of the Starter Kit or use the code I've provided here.


&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-4134251031648887394&amp;page=RSS%3a+RPG+Game+Development+-+Part+6&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=machaira.spaces.live.com&amp;amp;GT1=machaira"&gt;</description><comments>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!478.entry#comment</comments><guid isPermaLink="true">http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!478.entry</guid><pubDate>Thu, 27 Dec 2007 22:30:54 GMT</pubDate><slash:comments>2</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://machaira.spaces.live.com/blog/cns!C6A0309746469D9E!478/comments/feed.rss</wfw:commentRss><wfw:comment>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!478.entry#comment</wfw:comment><dcterms:modified>2007-12-27T22:30:54Z</dcterms:modified></item><item><title>RPG Game Development - Part 3</title><link>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!455.entry</link><description>&lt;p&gt;An RPG is useless unless the character can do something in the world, thus the need for a Skill class, which we'll talk about in this post. &lt;p&gt;  &lt;p&gt;The first thing we need to do is define what type of skills we can have. For now, we'll limit them to 3:&lt;pre&gt;    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;enum&lt;/span&gt; SkillType
    {
        Defensive,
        NonCombat,
        Offensive
    }&lt;/pre&gt;


&lt;p&gt; 
&lt;p&gt;Our Skill class looks like this:
&lt;p&gt; &lt;pre&gt;    [Serializable]
    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; Skill
    {
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _id;
        &lt;span&gt;private&lt;/span&gt; String _name;
        &lt;span&gt;private&lt;/span&gt; String _description;

        &lt;span&gt;private&lt;/span&gt; SkillType _type;

        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _preferredClassID;

        &lt;span&gt;private&lt;/span&gt; Dictionary&amp;lt;&lt;span&gt;int&lt;/span&gt;, &lt;span&gt;string&lt;/span&gt;&amp;gt; _costs;
        &lt;span&gt;private&lt;/span&gt; Dictionary&amp;lt;&lt;span&gt;int&lt;/span&gt;,&lt;span&gt;int&lt;/span&gt;&amp;gt; _classBonuses;
        &lt;span&gt;private&lt;/span&gt; List&amp;lt;MinMaxBonus&amp;gt; _levelBonuses;
        &lt;span&gt;private&lt;/span&gt; Dictionary&amp;lt;&lt;span&gt;int&lt;/span&gt;, &lt;span&gt;int&lt;/span&gt;&amp;gt; _raceBonuses;
        &lt;span&gt;private&lt;/span&gt; Dictionary&amp;lt;&lt;span&gt;int&lt;/span&gt;, MinMaxBonus&amp;gt; _statBonuses;

        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;bool&lt;/span&gt; _alwaysOn;

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; ID
        {
            get { &lt;span&gt;return&lt;/span&gt; _id; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; Name
        {
            get { &lt;span&gt;return&lt;/span&gt; _name; }
            set { &lt;span&gt;if&lt;/span&gt; (&lt;span&gt;value&lt;/span&gt;.Length &amp;gt; 0) _name = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; Description
        {
            get { &lt;span&gt;return&lt;/span&gt; _description; }
            set { &lt;span&gt;if&lt;/span&gt; (&lt;span&gt;value&lt;/span&gt;.Length &amp;gt; 0) _description = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; SkillType Type
        {
            get { &lt;span&gt;return&lt;/span&gt; _type; }
            set { _type = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; PreferredClassID
        {
            get { &lt;span&gt;return&lt;/span&gt; _preferredClassID; }
            set { _preferredClassID = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;bool&lt;/span&gt; AlwaysOn
        {
            get { &lt;span&gt;return&lt;/span&gt; _alwaysOn; }
            set { _alwaysOn = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; Skill(&lt;span&gt;int&lt;/span&gt; id)
        {
            _costs = &lt;span&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span&gt;int&lt;/span&gt;, &lt;span&gt;string&lt;/span&gt;&amp;gt;();
            _classBonuses = &lt;span&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span&gt;int&lt;/span&gt;, &lt;span&gt;int&lt;/span&gt;&amp;gt;();
            _raceBonuses = &lt;span&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span&gt;int&lt;/span&gt;, &lt;span&gt;int&lt;/span&gt;&amp;gt;();
            _levelBonuses = &lt;span&gt;new&lt;/span&gt; List&amp;lt;MinMaxBonus&amp;gt;();
            _statBonuses = &lt;span&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span&gt;int&lt;/span&gt;, MinMaxBonus&amp;gt;();
            _alwaysOn = &lt;span&gt;false&lt;/span&gt;;

            _id = id;

        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; AddCost(&lt;span&gt;int&lt;/span&gt; id, &lt;span&gt;string&lt;/span&gt; cost)
        {
            &lt;span&gt;if&lt;/span&gt; (_costs == &lt;span&gt;null&lt;/span&gt;)
                _costs = &lt;span&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span&gt;int&lt;/span&gt;, &lt;span&gt;string&lt;/span&gt;&amp;gt;();

            _costs.Add(id, cost);

        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; RemoveCost(&lt;span&gt;int&lt;/span&gt; id)
        {
            &lt;span&gt;if&lt;/span&gt; (_costs != &lt;span&gt;null&lt;/span&gt;)
                _costs.Remove(id);
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; GetCost(&lt;span&gt;int&lt;/span&gt; id)
        {
            &lt;span&gt;string&lt;/span&gt; cost = &lt;span&gt;&amp;quot;&amp;quot;&lt;/span&gt;;

            &lt;span&gt;if&lt;/span&gt; (_costs != &lt;span&gt;null&lt;/span&gt;)
                _costs.TryGetValue(id, &lt;span&gt;out&lt;/span&gt; cost);

            &lt;span&gt;return&lt;/span&gt; cost;
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; AddClassBonus(&lt;span&gt;int&lt;/span&gt; id, &lt;span&gt;string&lt;/span&gt; bonus)
        {
            &lt;span&gt;if&lt;/span&gt; (_classBonuses == &lt;span&gt;null&lt;/span&gt;)
                _classBonuses = &lt;span&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span&gt;int&lt;/span&gt;, &lt;span&gt;int&lt;/span&gt;&amp;gt;();

            _costs.Add(id, bonus);

        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; RemoveClassBonus(&lt;span&gt;int&lt;/span&gt; id)
        {
            &lt;span&gt;if&lt;/span&gt; (_classBonuses != &lt;span&gt;null&lt;/span&gt;)
                _classBonuses.Remove(id);
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; GetClassBonus(&lt;span&gt;int&lt;/span&gt; id)
        {
            &lt;span&gt;int&lt;/span&gt; bonus = 0;

            &lt;span&gt;if&lt;/span&gt; (_classBonuses != &lt;span&gt;null&lt;/span&gt;)
                _classBonuses.TryGetValue(id, &lt;span&gt;out&lt;/span&gt; bonus);

            &lt;span&gt;return&lt;/span&gt; bonus;
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; AddRaceBonus(&lt;span&gt;int&lt;/span&gt; id, &lt;span&gt;int&lt;/span&gt; bonus)
        {
            &lt;span&gt;if&lt;/span&gt; (_raceBonuses == &lt;span&gt;null&lt;/span&gt;)
                _raceBonuses = &lt;span&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span&gt;int&lt;/span&gt;, &lt;span&gt;int&lt;/span&gt;&amp;gt;();

            _raceBonuses.Add(id, bonus);

        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; RemoveRaceBonus(&lt;span&gt;int&lt;/span&gt; id)
        {
            &lt;span&gt;if&lt;/span&gt; (_raceBonuses != &lt;span&gt;null&lt;/span&gt;)
                _raceBonuses.Remove(id);
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; GetRaceBonus(&lt;span&gt;int&lt;/span&gt; id)
        {
            &lt;span&gt;int&lt;/span&gt; bonus = 0;

            &lt;span&gt;if&lt;/span&gt; (_raceBonuses != &lt;span&gt;null&lt;/span&gt;)
                _raceBonuses.TryGetValue(id, &lt;span&gt;out&lt;/span&gt; bonus);

            &lt;span&gt;return&lt;/span&gt; bonus;
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; AddStatBonus(&lt;span&gt;int&lt;/span&gt; id, MinMaxBonus bonus)
        {
            &lt;span&gt;if&lt;/span&gt; (_statBonuses == &lt;span&gt;null&lt;/span&gt;)
                _statBonuses = &lt;span&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span&gt;int&lt;/span&gt;, MinMaxBonus&amp;gt;();

            _statBonuses.Add(id, bonus);

        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; RemoveStatBonus(&lt;span&gt;int&lt;/span&gt; id)
        {
            &lt;span&gt;if&lt;/span&gt; (_statBonuses != &lt;span&gt;null&lt;/span&gt;)
                _statBonuses.Remove(id);
        }

        &lt;span&gt;public&lt;/span&gt; MinMaxBonus GetStatBonus(&lt;span&gt;int&lt;/span&gt; id)
        {
            MinMaxBonus bonus = &lt;span&gt;new&lt;/span&gt; MinMaxBonus();

            &lt;span&gt;if&lt;/span&gt; (_statBonuses != &lt;span&gt;null&lt;/span&gt;)
                _statBonuses.TryGetValue(id, &lt;span&gt;out&lt;/span&gt; bonus);

            &lt;span&gt;return&lt;/span&gt; bonus;
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; AddLevelBonus(MinMaxBonus bonus)
        {
            &lt;span&gt;if&lt;/span&gt; (_levelBonuses == &lt;span&gt;null&lt;/span&gt;)
                _levelBonuses = &lt;span&gt;new&lt;/span&gt; List&amp;lt;MinMaxBonus&amp;gt;();

            _levelBonuses.Add(bonus);

        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; RemoveLevelBonus(&lt;span&gt;int&lt;/span&gt; index)
        {
            &lt;span&gt;if&lt;/span&gt; (_levelBonuses != &lt;span&gt;null&lt;/span&gt;)
                _levelBonuses.RemoveAt(index);
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; GetLevelBonus(&lt;span&gt;int&lt;/span&gt; level)
        {
            &lt;span&gt;if&lt;/span&gt; (_levelBonuses != &lt;span&gt;null&lt;/span&gt;)
            {
                &lt;span&gt;foreach&lt;/span&gt; (MinMaxBonus bonus &lt;span&gt;in&lt;/span&gt; _levelBonuses)
                {
                    &lt;span&gt;if&lt;/span&gt; (bonus.IsValueInRange(level))
                        &lt;span&gt;return&lt;/span&gt; bonus.Amount;
                }
            }

            &lt;span&gt;return&lt;/span&gt; 0;
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;bool&lt;/span&gt; Use(&lt;span&gt;ref&lt;/span&gt; Object target, &lt;span&gt;ref&lt;/span&gt; Entity caster, Difficulty difficulty, &lt;span&gt;ref&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; result)
        {

            &lt;span&gt;int&lt;/span&gt; roll;
            &lt;span&gt;int&lt;/span&gt; bns = 0;

            roll = GlobalFunctions.GetRandomNumber(DieType.d100);

            roll += (Int16)difficulty;

            &lt;span&gt;switch&lt;/span&gt; (_type)
            {
                &lt;span&gt;case&lt;/span&gt; SkillType.Defensive:
                {
                    roll += ((Entity)target).GetTotalOffBonus();
                    &lt;span&gt;break&lt;/span&gt;;
                }
                &lt;span&gt;case&lt;/span&gt; SkillType.NonCombat:
                {
                    roll += ((Entity)target).GetTotalMiscBonus();
                    &lt;span&gt;break&lt;/span&gt;;
                }
                &lt;span&gt;case&lt;/span&gt; SkillType.Offensive:
                {
                    roll += ((Entity)target).GetTotalDefBonus();
                    &lt;span&gt;break&lt;/span&gt;;
                }
            }

            &lt;span&gt;//Calculate level bonus&lt;/span&gt;
            &lt;span&gt;if&lt;/span&gt; (_levelBonuses == &lt;span&gt;null&lt;/span&gt;)
            {
                Int16 level = caster.Level;
                &lt;span&gt;//use default&lt;/span&gt;
                &lt;span&gt;switch&lt;/span&gt; (level)
                {
                    &lt;span&gt;case&lt;/span&gt; 1:
                    &lt;span&gt;case&lt;/span&gt; 2:
                    &lt;span&gt;case&lt;/span&gt; 3:
                    &lt;span&gt;case&lt;/span&gt; 4:
                    &lt;span&gt;case&lt;/span&gt; 5:
                    {
                        bns = (Int16)(10 * level);
                        &lt;span&gt;break&lt;/span&gt;;
                    }
                    &lt;span&gt;case&lt;/span&gt; 6:
                    &lt;span&gt;case&lt;/span&gt; 7:
                    &lt;span&gt;case&lt;/span&gt; 8:
                    &lt;span&gt;case&lt;/span&gt; 9:
                    &lt;span&gt;case&lt;/span&gt; 10:
                    {
                        bns = (Int16)(50 + (5 * (level - 5)));
                        &lt;span&gt;break&lt;/span&gt;;
                    }
                    &lt;span&gt;case&lt;/span&gt; 11:
                    &lt;span&gt;case&lt;/span&gt; 12:
                    &lt;span&gt;case&lt;/span&gt; 13:
                    &lt;span&gt;case&lt;/span&gt; 14:
                    &lt;span&gt;case&lt;/span&gt; 15:
                    {
                        bns = (Int16)(75 + (3 * (level - 10)));
                        &lt;span&gt;break&lt;/span&gt;;
                    }
                    &lt;span&gt;case&lt;/span&gt; 16:
                    &lt;span&gt;case&lt;/span&gt; 17:
                    &lt;span&gt;case&lt;/span&gt; 18:
                    &lt;span&gt;case&lt;/span&gt; 19:
                    &lt;span&gt;case&lt;/span&gt; 20:
                    {
                        bns = (Int16)(90 + (2 * (level - 15)));
                        &lt;span&gt;break&lt;/span&gt;;
                    }
                    &lt;span&gt;default&lt;/span&gt;:
                    {
                        bns = (Int16)(100 + (1 * (level - 20)));
                        &lt;span&gt;break&lt;/span&gt;;
                    }
                }
            }
            &lt;span&gt;else&lt;/span&gt;
            {
                &lt;span&gt;foreach&lt;/span&gt; (MinMaxBonus bonus &lt;span&gt;in&lt;/span&gt; _levelBonuses)
                {
                    &lt;span&gt;if&lt;/span&gt; (bonus.IsValueInRange(caster.Level))
                    {
                        bns += bonus.Amount;
                        &lt;span&gt;break&lt;/span&gt;;
                    }
                }
            }

            roll += bns;

            result = roll;

            &lt;span&gt;if&lt;/span&gt; (roll &amp;gt;= 100)
                &lt;span&gt;return&lt;/span&gt; &lt;span&gt;true&lt;/span&gt;;
            &lt;span&gt;else&lt;/span&gt;
                &lt;span&gt;return&lt;/span&gt; &lt;span&gt;false&lt;/span&gt;;

        }
    }
&lt;/pre&gt;


&lt;p&gt; 
&lt;p&gt;The first couple of properties are straightforward. The _preferredClassID property allows a bonus to be added if the character that's using that skill is of the preferred class (for example, rangers tend to be better with at tracking than non-rangers). You can use either that property or just assign a bigger amount to the Ranger item in the _classBonuses member. I've tried to give some flexibility to the class so you can use it how you need to for your game.
&lt;p&gt; 
&lt;p&gt;The _costs member represents the idea that in some system it costs the character something to train in a skill. This could be points that the character gets each level, in a level-based system, to use in training in whatever skills they desire. In a skill-based system, the character would get better at a skill a little each time he successfully uses it. In that case you could either add a property to tell how often the skill would increase or use the _levelBonuses member, having one or more items in the list to get a range or number of times the skill needs to be used to increase the ability with it.
&lt;p&gt; 
&lt;p&gt;The _classBonuses and _raceBonuses are a set amount for each class and race. The _levelBonuses and _statBonuses allow you to specify an amount for a range of levels or stat values. The MinMaxBonus is a simple structure that looks like this:
&lt;p&gt; &lt;pre&gt;
    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;struct&lt;/span&gt; MinMaxBonus
    {
        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; Min;
        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; Max;
        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; Amount;

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;bool&lt;/span&gt; IsValueInRange(&lt;span&gt;int&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;)
        {
            &lt;span&gt;return&lt;/span&gt; (&lt;span&gt;value&lt;/span&gt; &amp;gt;= Min &amp;amp;&amp;amp; &lt;span&gt;value&lt;/span&gt; &amp;lt;= Max);
        }
    }&lt;/pre&gt;


&lt;p&gt; 
&lt;p&gt;The _alwaysOn member allows you to have skills that don't require an explicit use of the skill. For example, you could have a Perception skill where the game allows the character a chance of noticing something without the player actively searching the area he's in. The game would just check to see if the character had that skill and use it. If the use succeeded the character would be notified. This is more so that the player can be told that the skill is something that doesn't always require their explicit initiation of the skill (say, in a skill select dialog).
&lt;p&gt; 
&lt;p&gt;The typical functionality of adding, removing, and getting items in the list exist and the Use function allows the game to see if an attempt by the character at using the skill succeeds and, if so, by how much). The target is an instance of an Object class since a skill can be used on more than just an Entity (say casting a Remove Trap spell on a chest or casting an area effect spell).
&lt;p&gt; 
&lt;p&gt;The Use function gets a random number from 1-100 (if your system uses a different range you'll have to change this obviously) then checks to see how difficult the task the character is attempting to perform is. This is represented by an enum with values that are added to the roll:
&lt;p&gt; &lt;pre&gt;    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;enum&lt;/span&gt; Difficulty
    {
        Impossible = -50,
        VeryHard = -25,
        Hard = -10,
        Normal = 0,
        Easy = 10,
        VeryEasy = 25
    }&lt;/pre&gt;
&lt;p&gt;


&lt;p&gt;This is another area that you can tweak for your game. After adding this the bonuses for the character performing the attempt and entity the skill is being used on are added up. This value (which can be positive or negative) is added to the roll. If the value of the roll is greater than 100 the attempt succeeds. The roll is returned to the calling code in order to allow for things like critical success or failure results. If the character makes a stupendous effort or fails spectacularly, the calling code can do something specific (say the character drops his weapon is the result is less than a certain amount or the attempt takes less time than normal if the result is a certain amount over 100, allowing him to perform another action when he normally wouldn't be able to).
&lt;p&gt; 
&lt;p&gt;We'll track the skills an Entity has by keeping a list of EntitySkill objects:
&lt;p&gt; &lt;pre&gt;    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; EntitySkill
    {
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _id;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _amount;

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; Amount
        {
            get { &lt;span&gt;return&lt;/span&gt; _amount; }
        }

        &lt;span&gt;public&lt;/span&gt; EntitySkill(&lt;span&gt;int&lt;/span&gt; id, &lt;span&gt;int&lt;/span&gt; amount)
        {
            _id = id;
            _amount = amount;
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; Increase(&lt;span&gt;int&lt;/span&gt; amount)
        {
            _amount += amount;
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; Decrease(&lt;span&gt;int&lt;/span&gt; amount)
        {
            _amount -= amount;
        }
    }&lt;/pre&gt;
&lt;p&gt; 
&lt;p&gt;This class tells us the ID of the skill and how much he's trained in it. It also allows for the amount to be increased or decreased, say through lack of use.
&lt;p&gt; 
&lt;p&gt;We now have one more chunk of code done for our system. The next post will probably be a big one as we'll look at our item system. As always feel free to give me your feedback on this post in the forums &lt;a href="http://www.machxgames.com/forum/default.aspx?g=posts&amp;amp;t=30" target="_blank"&gt;here&lt;/a&gt;.
&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-4134251031648887394&amp;page=RSS%3a+RPG+Game+Development+-+Part+3&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=machaira.spaces.live.com&amp;amp;GT1=machaira"&gt;</description><comments>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!455.entry#comment</comments><guid isPermaLink="true">http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!455.entry</guid><pubDate>Mon, 10 Dec 2007 21:42:42 GMT</pubDate><slash:comments>2</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://machaira.spaces.live.com/blog/cns!C6A0309746469D9E!455/comments/feed.rss</wfw:commentRss><wfw:comment>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!455.entry#comment</wfw:comment><dcterms:modified>2007-12-10T21:42:42Z</dcterms:modified></item><item><title>RPG Game Development - Part 2</title><link>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!453.entry</link><description>&lt;p&gt;If you picture a character from an RPG in your mind what stands out? If you said anything other than the race of the character and their class (or profession), feel free to come back when you've gotten with the program. :) 
&lt;p&gt;  
&lt;p&gt;OK, now that we know what we'll be talking about this time around, let's see what we're dealing with. Every fantasy-based RPG that I can recall and most sci-fi RPGs incorporate multiple races to allow the player some freedom in helping select how they'll play the game as well as make the game a bit more interesting since you're not constantly running into just humans (or whatever the main race is in the game). One race is usually better at one or more things than others, so if you like to play an RPG a certain way you'll probably pick one race the first time around (assuming you play the game more than once). 
&lt;p&gt;  
&lt;p&gt;One of the usual steroetypes have elves as the best class that use a bow (which makes them the best for a ranger-type character or fighter that specializes in long-ranged attacks) and sometimes magic-users, although they're usually weak physically. There's also the added benefit of night-vision and sometimes resistance to magic, poisons, and disease. 
&lt;p&gt;  
&lt;p&gt;Dwarves are stout, hardy fellows that make good fighters. Halflings and sometimes half-elfs make good thiefs. Humans are usually pretty good at everything while specializing in nothing. Playing as a human means you can go in whatever direction you want at any time, assuming you're not locked into a specific class for the entire game (as is the case with RPGs that strictly go the skill-based route). 
&lt;p&gt;  
&lt;p&gt;Looking at these stereotypes it seems we need a way to modify a character's stats, skills, and what we'll call resistances and weaknesses. While we haven't defined anything but stats at this point, it's a fairly safe assumption that the values will be integers. That being said, here's a first cut: 
&lt;p&gt; &lt;pre&gt;    [Serializable]
    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; Race
    {
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _id;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; _name = &lt;span&gt;&amp;quot;&amp;quot;&lt;/span&gt;;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; _description = &lt;span&gt;&amp;quot;&amp;quot;&lt;/span&gt;;

        &lt;span&gt;private&lt;/span&gt; Dictionary&amp;lt;&lt;span&gt;int&lt;/span&gt;, &lt;span&gt;int&lt;/span&gt;&amp;gt; _statModifiers;
        &lt;span&gt;private&lt;/span&gt; Dictionary&amp;lt;&lt;span&gt;int&lt;/span&gt;, &lt;span&gt;int&lt;/span&gt;&amp;gt; _skillModifiers;

        &lt;span&gt;private&lt;/span&gt; List&amp;lt;Modifier&amp;gt; _weaknesses;
        &lt;span&gt;private&lt;/span&gt; List&amp;lt;Modifier&amp;gt; _resistances;

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; ID
        {
            get { &lt;span&gt;return&lt;/span&gt; _id; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; Name
        {
            get { &lt;span&gt;return&lt;/span&gt; _name; }
            set { &lt;span&gt;if&lt;/span&gt; (_name.Length &amp;gt; 0) _name = &lt;span&gt;value&lt;/span&gt;; }
        }
        
        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; Description
        {
            get { &lt;span&gt;return&lt;/span&gt; _description; }
            set { &lt;span&gt;if&lt;/span&gt; (&lt;span&gt;value&lt;/span&gt;.Length &amp;gt; 0) _description = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; Race(&lt;span&gt;int&lt;/span&gt; id)
        {
            _id = id;
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; GetStatModifier(&lt;span&gt;int&lt;/span&gt; id)
        {
            &lt;span&gt;int&lt;/span&gt; &lt;span&gt;value&lt;/span&gt; = 0;

            &lt;span&gt;if&lt;/span&gt; (_statModifiers != &lt;span&gt;null&lt;/span&gt;)
                _statModifiers.TryGetValue(id, &lt;span&gt;out&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;);

            &lt;span&gt;return&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;;
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; GetSkillModifier(&lt;span&gt;int&lt;/span&gt; id)
        {
            &lt;span&gt;int&lt;/span&gt; &lt;span&gt;value&lt;/span&gt; = 0;

            &lt;span&gt;if&lt;/span&gt; (_skillModifiers != &lt;span&gt;null&lt;/span&gt;)
                _skillModifiers.TryGetValue(id, &lt;span&gt;out&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;);

            &lt;span&gt;return&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;;
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; AddStatModifier(&lt;span&gt;int&lt;/span&gt; id, &lt;span&gt;int&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;)
        {
            &lt;span&gt;if&lt;/span&gt; (_statModifiers == &lt;span&gt;null&lt;/span&gt;)
                _statModifiers = &lt;span&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span&gt;int&lt;/span&gt;, &lt;span&gt;int&lt;/span&gt;&amp;gt;();

            _statModifiers.Add(id, &lt;span&gt;value&lt;/span&gt;);
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; AddSkillModifier(&lt;span&gt;int&lt;/span&gt; id, &lt;span&gt;int&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;)
        {
            &lt;span&gt;if&lt;/span&gt; (_skillModifiers == &lt;span&gt;null&lt;/span&gt;)
                _skillModifiers = &lt;span&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span&gt;int&lt;/span&gt;, &lt;span&gt;int&lt;/span&gt;&amp;gt;();

            _skillModifiers.Add(id, &lt;span&gt;value&lt;/span&gt;);
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; RemoveStatModifier(&lt;span&gt;int&lt;/span&gt; id)
        {
            &lt;span&gt;if&lt;/span&gt; (_statModifiers == &lt;span&gt;null&lt;/span&gt;)
                &lt;span&gt;return&lt;/span&gt;;

            _statModifiers.Remove(id);
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; RemoveSkillModifier(&lt;span&gt;int&lt;/span&gt; id)
        {
            &lt;span&gt;if&lt;/span&gt; (_skillModifiers == &lt;span&gt;null&lt;/span&gt;)
                &lt;span&gt;return&lt;/span&gt;;

            _skillModifiers.Remove(id);
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; AddWeakness(Modifier weakness)
        {
            &lt;span&gt;if&lt;/span&gt; (_weaknesses == &lt;span&gt;null&lt;/span&gt;)
                _weaknesses = &lt;span&gt;new&lt;/span&gt; List&amp;lt;Modifier&amp;gt;();

            _weaknesses.Add(weakness);
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; AddResistance(Modifier resistance)
        {
            &lt;span&gt;if&lt;/span&gt; (_resistances == &lt;span&gt;null&lt;/span&gt;)
                _resistances = &lt;span&gt;new&lt;/span&gt; List&amp;lt;Modifier&amp;gt;();

            _resistances.Add(resistance);
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; RemoveWeakness(&lt;span&gt;int&lt;/span&gt; index)
        {
            &lt;span&gt;if&lt;/span&gt; (_weaknesses == &lt;span&gt;null&lt;/span&gt;)
                &lt;span&gt;return&lt;/span&gt;;

            _weaknesses.RemoveAt(index);
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; RemoveResistance(&lt;span&gt;int&lt;/span&gt; index)
        {
            &lt;span&gt;if&lt;/span&gt; (_resistances == &lt;span&gt;null&lt;/span&gt;)
                &lt;span&gt;return&lt;/span&gt;;

            _resistances.RemoveAt(index);
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; CheckResistance(ModifierType type)
        {
            &lt;span&gt;if&lt;/span&gt; (_resistances == &lt;span&gt;null&lt;/span&gt;)
                &lt;span&gt;return&lt;/span&gt; 0;

            &lt;span&gt;foreach&lt;/span&gt; (Modifier resistance &lt;span&gt;in&lt;/span&gt; _resistances)
            {
                &lt;span&gt;if&lt;/span&gt; (resistance.Type == type)
                {
                    &lt;span&gt;return&lt;/span&gt; resistance.Amount;
                }
            }

            &lt;span&gt;return&lt;/span&gt; 0;
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; CheckWeakness(ModifierType type)
        {
            &lt;span&gt;if&lt;/span&gt; (_weaknesses == &lt;span&gt;null&lt;/span&gt;)
                &lt;span&gt;return&lt;/span&gt; 0;

            &lt;span&gt;foreach&lt;/span&gt; (Modifier weakness &lt;span&gt;in&lt;/span&gt; _weaknesses)
            {
                &lt;span&gt;if&lt;/span&gt; (weakness.Type == type)
                {
                    &lt;span&gt;return&lt;/span&gt; weakness.Amount;
                }
            }

            &lt;span&gt;return&lt;/span&gt; 0;
        }
    }
&lt;/pre&gt;
&lt;p&gt;  
&lt;p&gt;At this point we just have an ID that we'll use as a link in the upcoming Entity class, a name and description, two Dictionary objects for allowing modifications to stats and skills (the first part of the Dictionary is the ID of the stat or skill and the second is the positive or negative value to modify that stat or skill), and two lists for allowing resistances and weaknesses for a race. The Modifer object is a structure whose definition is: 
&lt;p&gt; &lt;pre&gt;    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;struct&lt;/span&gt; Modifier
    {
        &lt;span&gt;public&lt;/span&gt; ModifierType Type;
        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; Amount;
    }&lt;/pre&gt;
&lt;p&gt;  
&lt;p&gt;ModifierType is an enum: 
&lt;p&gt; &lt;pre&gt;   &lt;span&gt;public&lt;/span&gt; &lt;span&gt;enum&lt;/span&gt; ModifierType
    {
        Fire,
        Water,
        Magic,
        Disease,
        Poison
    }&lt;/pre&gt;
&lt;p&gt;  
&lt;p&gt;Feel free to add to the list. You could even make ModiferType something that's read from a file to make it dynamic. In that case you might want to make it a structure as well with an ID property and a value so it can be changed without breaking the links to objects that use it. 
&lt;p&gt;  
&lt;p&gt;&lt;font size=4&gt;&lt;u&gt;The EntityClass class&lt;/u&gt;&lt;/font&gt; 
&lt;p&gt;  
&lt;p&gt;The EntityClass class is similar to the Race class in that it allows the character to be better and worse at some skills and it modifies stats to represent the intense training members of that class undergo. It also allows items to only be usable by certain classes and races to be only certain classes. If you want to do race/class restrictions, simply add a List&amp;lt;EntityClass&amp;gt; member to the Race class to indicate the allowed classes that the race may be along with the appropriate code to handle add and removing items from it. Using this class, however, is completely optional if you want your RPG to be strictly skill-based. 
&lt;p&gt; &lt;pre&gt; &lt;/pre&gt;&lt;pre&gt;    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; EntityClass
    {
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _id;

        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; _name = &lt;span&gt;&amp;quot;&amp;quot;&lt;/span&gt;;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; _description = &lt;span&gt;&amp;quot;&amp;quot;&lt;/span&gt;;

        &lt;span&gt;private&lt;/span&gt; Dictionary&amp;lt;&lt;span&gt;int&lt;/span&gt;, &lt;span&gt;int&lt;/span&gt;&amp;gt; _statModifiers;
        &lt;span&gt;private&lt;/span&gt; Dictionary&amp;lt;&lt;span&gt;int&lt;/span&gt;, &lt;span&gt;int&lt;/span&gt;&amp;gt; _skillModifiers;

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; ID
        {
            get { &lt;span&gt;return&lt;/span&gt; _id; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; Name
        {
            get { &lt;span&gt;return&lt;/span&gt; _name; }
            set { &lt;span&gt;if&lt;/span&gt; (_name.Length &amp;gt; 0) _name = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; Description
        {
            get { &lt;span&gt;return&lt;/span&gt; _description; }
            set { &lt;span&gt;if&lt;/span&gt; (&lt;span&gt;value&lt;/span&gt;.Length &amp;gt; 0) _description = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; GetStatModifier(&lt;span&gt;int&lt;/span&gt; id)
        {
            &lt;span&gt;int&lt;/span&gt; &lt;span&gt;value&lt;/span&gt; = 0;

            &lt;span&gt;if&lt;/span&gt; (_statModifiers != &lt;span&gt;null&lt;/span&gt;)
                _statModifiers.TryGetValue(id, &lt;span&gt;out&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;);

            &lt;span&gt;return&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;;
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; GetSkillModifier(&lt;span&gt;int&lt;/span&gt; id)
        {
            &lt;span&gt;int&lt;/span&gt; &lt;span&gt;value&lt;/span&gt; = 0;

            &lt;span&gt;if&lt;/span&gt; (_skillModifiers != &lt;span&gt;null&lt;/span&gt;)
                _skillModifiers.TryGetValue(id, &lt;span&gt;out&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;);

            &lt;span&gt;return&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;;
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; AddStatModifier(&lt;span&gt;int&lt;/span&gt; id, &lt;span&gt;int&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;)
        {
            &lt;span&gt;if&lt;/span&gt; (_statModifiers == &lt;span&gt;null&lt;/span&gt;)
                _statModifiers = &lt;span&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span&gt;int&lt;/span&gt;, &lt;span&gt;int&lt;/span&gt;&amp;gt;();

            _statModifiers.Add(id, &lt;span&gt;value&lt;/span&gt;);
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; AddSkillModifier(&lt;span&gt;int&lt;/span&gt; id, &lt;span&gt;int&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;)
        {
            &lt;span&gt;if&lt;/span&gt; (_skillModifiers == &lt;span&gt;null&lt;/span&gt;)
                _skillModifiers = &lt;span&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span&gt;int&lt;/span&gt;, &lt;span&gt;int&lt;/span&gt;&amp;gt;();

            _skillModifiers.Add(id, &lt;span&gt;value&lt;/span&gt;);
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; RemoveStatModifier(&lt;span&gt;int&lt;/span&gt; id)
        {
            &lt;span&gt;if&lt;/span&gt; (_statModifiers == &lt;span&gt;null&lt;/span&gt;)
                &lt;span&gt;return&lt;/span&gt;;

            _statModifiers.Remove(id);
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; RemoveSkillModifier(&lt;span&gt;int&lt;/span&gt; id)
        {
            &lt;span&gt;if&lt;/span&gt; (_skillModifiers == &lt;span&gt;null&lt;/span&gt;)
                &lt;span&gt;return&lt;/span&gt;;

            _skillModifiers.Remove(id);
        }
    }
&lt;/pre&gt;
&lt;p&gt;  
&lt;p&gt;&lt;font size=4&gt;&lt;u&gt;Manager Classes&lt;/u&gt;&lt;/font&gt; 
&lt;p&gt;  
&lt;p&gt;We'll need some classes to manage the Race and EntityClass objects. They're fairly simple at this point: 
&lt;p&gt; &lt;pre&gt;    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; StatManager
    {
        &lt;span&gt;private&lt;/span&gt; List&amp;lt;Stat&amp;gt; _stats;

        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;static&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _numStats = 0;

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;static&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; NumStats
        {
            get { &lt;span&gt;return&lt;/span&gt; _numStats; }
        }

        &lt;span&gt;public&lt;/span&gt; StatManager()
        {
            _stats = &lt;span&gt;new&lt;/span&gt; List&amp;lt;Stat&amp;gt;();
        }

        &lt;span&gt;public&lt;/span&gt; StatManager(&lt;span&gt;string&lt;/span&gt; filename)
        {
            &lt;span&gt;if&lt;/span&gt; (File.Exists(filename))
            {
                XmlSerializer serializer = &lt;span&gt;new&lt;/span&gt; XmlSerializer(&lt;span&gt;typeof&lt;/span&gt;(Stat));

                FileStream fs = &lt;span&gt;new&lt;/span&gt; FileStream(filename, FileMode.Open);

                _stats = (List&amp;lt;Stat&amp;gt;)serializer.Deserialize(fs);

                _numStats = _stats.Count;
            }
        }

        &lt;span&gt;public&lt;/span&gt; Stat GetStat(&lt;span&gt;int&lt;/span&gt; id)
        {
            &lt;span&gt;foreach&lt;/span&gt; (Stat stat &lt;span&gt;in&lt;/span&gt; _stats)
            {
                &lt;span&gt;if&lt;/span&gt; (stat.ID == id)
                    &lt;span&gt;return&lt;/span&gt; stat;
                &lt;span&gt;break&lt;/span&gt;;
            }

            &lt;span&gt;return&lt;/span&gt; &lt;span&gt;null&lt;/span&gt;;
        }
    }

    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; RaceManager
    {
        &lt;span&gt;private&lt;/span&gt; List&amp;lt;Race&amp;gt; _races;

        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;static&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _numRaces = 0;

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;static&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; NumRaces
        {
            get { &lt;span&gt;return&lt;/span&gt; _numRaces; }
        }

        &lt;span&gt;public&lt;/span&gt; RaceManager(&lt;span&gt;string&lt;/span&gt; filename)
        {
            &lt;span&gt;if&lt;/span&gt; (File.Exists(filename))
            {
                XmlSerializer serializer = &lt;span&gt;new&lt;/span&gt; XmlSerializer(&lt;span&gt;typeof&lt;/span&gt;(Race));

                FileStream fs = &lt;span&gt;new&lt;/span&gt; FileStream(filename, FileMode.Open);

                _races = (List&amp;lt;Race&amp;gt;)serializer.Deserialize(fs);

                _numRaces = _races.Count;
            }
        }

        &lt;span&gt;public&lt;/span&gt; Race GetRace(&lt;span&gt;int&lt;/span&gt; id)
        {
            &lt;span&gt;foreach&lt;/span&gt; (Race race &lt;span&gt;in&lt;/span&gt; _races)
            {
                &lt;span&gt;if&lt;/span&gt; (race.ID == id)
                    &lt;span&gt;return&lt;/span&gt; race;
                &lt;span&gt;break&lt;/span&gt;;
            }

            &lt;span&gt;return&lt;/span&gt; &lt;span&gt;null&lt;/span&gt;;
        }
    }

    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; EntityClassManager
    {
        &lt;span&gt;private&lt;/span&gt; List&amp;lt;EntityClass&amp;gt; _classes;

        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;static&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _numClasses = 0;

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;static&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; NumClasses
        {
            get { &lt;span&gt;return&lt;/span&gt; _numClasses; }
        }

        &lt;span&gt;public&lt;/span&gt; EntityClassManager(&lt;span&gt;string&lt;/span&gt; filename)
        {
            &lt;span&gt;if&lt;/span&gt; (File.Exists(filename))
            {
                XmlSerializer serializer = &lt;span&gt;new&lt;/span&gt; XmlSerializer(&lt;span&gt;typeof&lt;/span&gt;(EntityClass));

                FileStream fs = &lt;span&gt;new&lt;/span&gt; FileStream(filename, FileMode.Open);

                _classes = (List&amp;lt;EntityClass&amp;gt;)serializer.Deserialize(fs);

                _numClasses = _classes.Count;
            }
        }

        &lt;span&gt;public&lt;/span&gt; EntityClass GetEntityClass(&lt;span&gt;int&lt;/span&gt; id)
        {
            &lt;span&gt;foreach&lt;/span&gt; (EntityClass entityClass &lt;span&gt;in&lt;/span&gt; _classes)
            {
                &lt;span&gt;if&lt;/span&gt; (entityClass.ID == id)
                    &lt;span&gt;return&lt;/span&gt; entityClass;
                &lt;span&gt;break&lt;/span&gt;;
            }

            &lt;span&gt;return&lt;/span&gt; &lt;span&gt;null&lt;/span&gt;;
        }
    }
&lt;/pre&gt;
&lt;p&gt;
&lt;p&gt;Note that I threw in the StatManager class as well that I omitted from the last post. 
&lt;p&gt;  
&lt;p&gt;The classes assume that the items will exist in an XML serialized file. If you want to use another method, such as binary serialization, simply change the serializer object (or all loading code) as appropriate. XML serialization won't prevent players from looking into the files to see the data, but for our purposes it's not worth the effort to try to obfuscate the data. XML is easily read while debugging the code that uses it, making it a nice format for developers to allow tweaking of values in testing. Once you've balanced the data you can simply change the loading and saving code if you'd like. 
&lt;p&gt;  
&lt;p&gt;The nice thing about having a manager class like this is the static member that allows code to get the number of items without having to create an instance of the class. 
&lt;p&gt;  
&lt;p&gt;That's it for this post. It's been a long one since we covered two classes, but we're almost at a point where we can tie it all together in an Entity object that will represent our character (and every other living creature) in a game. The next post will cover skills, which will allow an entity to perform actions, something that'll be fairly useful in a game. :) 
&lt;p&gt;You can discuss this post on the forums &lt;a href="http://www.machxgames.com/forum/default.aspx?g=posts&amp;amp;t=28" target="_blank"&gt;here&lt;/a&gt;.&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-4134251031648887394&amp;page=RSS%3a+RPG+Game+Development+-+Part+2&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=machaira.spaces.live.com&amp;amp;GT1=machaira"&gt;</description><comments>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!453.entry#comment</comments><guid isPermaLink="true">http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!453.entry</guid><pubDate>Mon, 10 Dec 2007 15:06:50 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://machaira.spaces.live.com/blog/cns!C6A0309746469D9E!453/comments/feed.rss</wfw:commentRss><wfw:comment>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!453.entry#comment</wfw:comment><dcterms:modified>2007-12-10T15:48:10Z</dcterms:modified></item><item><title>RPG Game Development - Part 1</title><link>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!452.entry</link><description>&lt;p&gt;I've been kicking around an RPG game for about 4 or 5 years. It's gone through several designs since each time new technology comes out I end up redoing it using that tech. It started out as a Visual Basic 6 game using DirectDraw. When Visual Studio.NET came out I started doing it in VB.NET and Managed DirectX. Now that XNA has come out and it's basically the only thing I'm doing game development in at this time, I've started redesigning it once again. Since many people that start out in game development seem to want to make an RPG (or an MMORPG depending on how old they are and what they were first exposed to in the RPG genre :D) and there seems to be a desire for more XNA starter kits, I thought it might be interesting to make this current version something that could be reused by other people. The next thought was, maybe I should make it generic enough that people that might use it wouldn't be stuck with the specific things I want to do in my RPG - types of stats, magic system, classes, etc. After all, not all RPGs are fantasy based so having just the typical Fighter, Magic-User, Thief, Cleric, Ranger classes in the kit might not be a good thing. 
&lt;p&gt;  
&lt;p&gt;Having made the decision to try to make this as generic as possible, I thought maybe I should solicit ideas from the community, which means getting my ideas and code out there so people can tear it apart... umm, make suggestions. This is the first in what I hope will be many posts that will end up with an RPG starter kit that budding XNA game developers (and even non-XNA developers, assuming they either convert the classes to whatever language they're using or using C# with some other technology) can use to create their dream RPG. 
&lt;p&gt;  
&lt;p&gt;&lt;strong&gt;&lt;u&gt;&lt;font size=4&gt;Stats&lt;/font&gt;&lt;/u&gt;&lt;/strong&gt; 
&lt;p&gt;In thinking about things, it seems the stat is one base for many other code classes. Characters use stats to figure out what profession they can follow (character classes), how well they can do things (skills),  and how well they can do them, so it seems to make sense to start with a stat class. Actually, I was thinking there would be multiple classes dealing with stats. The base stat class currently looks like this: 
&lt;p&gt; &lt;pre&gt;    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;enum&lt;/span&gt; StatType
    {
        Regular,
        Calculated
    }&lt;/pre&gt;&lt;pre&gt;    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;enum&lt;/span&gt; DieType
    {
        d4 = 4,
        d6 = 6,
        d8 = 8,
        d10 = 10,
        d12 = 12,
        d20 = 20,
        d100 = 100,
        MaxDie = 100
    }&lt;/pre&gt;&lt;pre&gt;    [Serializable()]
    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; Stat
    {
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _id;
        &lt;span&gt;private&lt;/span&gt; StatType _type;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; _name;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; _abbreviation;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; _description;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; _statCalculation;

        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;bool&lt;/span&gt; _addsToSkillPoints;
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;bool&lt;/span&gt; _addsToManaPoints;

        [NonSerialized()]
        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;const&lt;/span&gt; Int16 MAX_STAT_VALUE = (Int16)DieType.MaxDie;

        &lt;span&gt;public&lt;/span&gt; Stat(&lt;span&gt;int&lt;/span&gt; id, &lt;span&gt;string&lt;/span&gt; name)
        {
            _id = id;
            _name = name;
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; ID
        {
            get { &lt;span&gt;return&lt;/span&gt; _id; }
        }

        &lt;span&gt;public&lt;/span&gt; StatType Type
        {
            get { &lt;span&gt;return&lt;/span&gt; _type; }
            set { _type = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; Name
        {
            get { &lt;span&gt;return&lt;/span&gt; _name; }
            set { &lt;span&gt;if&lt;/span&gt; (&lt;span&gt;value&lt;/span&gt;.Length &amp;gt; 0) _name = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; Abbreviation
        {
            get { &lt;span&gt;return&lt;/span&gt; _abbreviation; }
            set { &lt;span&gt;if&lt;/span&gt; (&lt;span&gt;value&lt;/span&gt;.Length &amp;gt; 0) _abbreviation = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; Description
        {
            get { &lt;span&gt;return&lt;/span&gt; _description; }
            set { &lt;span&gt;if&lt;/span&gt; (&lt;span&gt;value&lt;/span&gt;.Length &amp;gt; 0) _description = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; StatCalculation
        {
            get { &lt;span&gt;return&lt;/span&gt; _statCalculation; }
            set { _statCalculation = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;bool&lt;/span&gt; AddsToSkillPoints
        {
            get { &lt;span&gt;return&lt;/span&gt; _addsToSkillPoints; }
            set { _addsToSkillPoints = &lt;span&gt;value&lt;/span&gt;; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;bool&lt;/span&gt; AddsToManaPoints
        {
            get { &lt;span&gt;return&lt;/span&gt; _addsToManaPoints; }
            set { _addsToManaPoints = &lt;span&gt;value&lt;/span&gt;; }
        }
    }
&lt;/pre&gt;&lt;pre&gt; &lt;/pre&gt;
&lt;p&gt;Having the StatType member allows the developer to have stats that are based on some calculation. For example, you could have a MaxCarryWeight stat that is calculated as some multiple of the character's Strength stat. This calculation is stored in the _statCalculation member. There should be some validation on this is the code or UI that populates it. 
&lt;p&gt;  
&lt;p&gt;The AddsTo... members are something that I'm using in my game and I thought might be useful to other developers. A character develops skills by spending a number of points each time he increases in level (the whole level argument is for another post ;D ). The number of points are calculated based on the value of certain stats. The same goes for a character's mana, which is a representation of how much a magic (or psionic for sci-fi RPGs)-using character can cast spells before becoming too drained to cast any more. Certain stats will be flagged as being used in the calculations. Tables will be developed later for the stat value-to-number of points ratio. 
&lt;p&gt;  
&lt;p&gt;Now that we have a basic stat class we need to have a way to tie them to a character. A simple cross-reference class takes care of this: 
&lt;p&gt; &lt;pre&gt;    [Serializable]
    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; EntityStat
    {
        &lt;span&gt;private&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; _id;
        &lt;span&gt;private&lt;/span&gt; Int16 _curValue;

        &lt;span&gt;public&lt;/span&gt; EntityStat(&lt;span&gt;int&lt;/span&gt; id, Int16 &lt;span&gt;value&lt;/span&gt;)
        {
            _id = id;
            _curValue = &lt;span&gt;value&lt;/span&gt;;
        }

        &lt;span&gt;public&lt;/span&gt; Int16 CurrentValue
        {
            get { &lt;span&gt;return&lt;/span&gt; _curValue; }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; IncreaseStat(Int16 val)
        {
            _curValue += val;
            &lt;span&gt;if&lt;/span&gt; (_curValue &amp;gt; Stat.MAX_STAT_VALUE)
                _curValue = Stat.MAX_STAT_VALUE;
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; ReduceStat(Int16 val)
        {
            _curValue -= val;
            &lt;span&gt;if&lt;/span&gt; (_curValue &amp;lt; 1)
                _curValue = 1;
        }
    }&lt;/pre&gt;
&lt;p&gt;
&lt;p&gt;The Entity class that will be developed later will have a list of this class. 
&lt;p&gt;  
&lt;p&gt;That's it for this edition of RPG Game Development. Stay tuned for the next post where we'll develop some other classes that will be used to fill out the Entity class, which will represent a player character, non-player character, or creature. 
&lt;p&gt;  
&lt;p&gt;If you want to discuss this post, head over to &lt;a href="http://www.machxgames.com/forum/default.aspx?g=posts&amp;amp;t=27" target="_blank"&gt;the post for this entry&lt;/a&gt; on the forums on my site. Unfortunately, I have to require registration due to spamming, but it's a quick and painless process, I promise. :) 
&lt;p&gt; &lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-4134251031648887394&amp;page=RSS%3a+RPG+Game+Development+-+Part+1&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=machaira.spaces.live.com&amp;amp;GT1=machaira"&gt;</description><comments>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!452.entry#comment</comments><guid isPermaLink="true">http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!452.entry</guid><pubDate>Wed, 05 Dec 2007 21:15:12 GMT</pubDate><slash:comments>2</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://machaira.spaces.live.com/blog/cns!C6A0309746469D9E!452/comments/feed.rss</wfw:commentRss><wfw:comment>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!452.entry#comment</wfw:comment><dcterms:modified>2007-12-05T21:18:49Z</dcterms:modified></item><item><title>Silverlight 1.1 tools for VS 2008</title><link>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!449.entry</link><description>&lt;p&gt;I've been meaning to check out Silverlight 1.1. There's been some cool little things released using it. I still have to install VS 2008 but once I do, I'll be installing &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=25144C27-6514-4AD4-8BCB-E2E051416E03&amp;amp;displaylang=en" target="_blank"&gt;this&lt;/a&gt; and checking it out.&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-4134251031648887394&amp;page=RSS%3a+Silverlight+1.1+tools+for+VS+2008&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=machaira.spaces.live.com&amp;amp;GT1=machaira"&gt;</description><comments>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!449.entry#comment</comments><guid isPermaLink="true">http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!449.entry</guid><pubDate>Wed, 28 Nov 2007 12:52:36 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://machaira.spaces.live.com/blog/cns!C6A0309746469D9E!449/comments/feed.rss</wfw:commentRss><wfw:comment>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!449.entry#comment</wfw:comment><dcterms:modified>2007-11-28T12:52:36Z</dcterms:modified></item><item><title>.NET Framework libraries source code to be released</title><link>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!415.entry</link><description>&lt;p&gt;An &lt;a href="http://weblogs.asp.net/scottgu/archive/2007/10/03/releasing-the-source-code-for-the-net-framework-libraries.aspx" target="_blank"&gt;interesting post&lt;/a&gt; on Scott Guthrie's blog has the news that the source code for the .NET Base Class Libraries will be released with the .NET 3.5 and VS 2008 release later this year. It's great to see that Microsoft continues to excel at releasing things to developers.&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-4134251031648887394&amp;page=RSS%3a+.NET+Framework+libraries+source+code+to+be+released&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=machaira.spaces.live.com&amp;amp;GT1=machaira"&gt;</description><comments>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!415.entry#comment</comments><guid isPermaLink="true">http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!415.entry</guid><pubDate>Thu, 04 Oct 2007 11:36:50 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://machaira.spaces.live.com/blog/cns!C6A0309746469D9E!415/comments/feed.rss</wfw:commentRss><wfw:comment>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!415.entry#comment</wfw:comment><dcterms:modified>2007-10-04T11:36:50Z</dcterms:modified></item><item><title>Visual Studio 2008 Beta 2 Downloads Available</title><link>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!370.entry</link><description>&lt;p&gt;Check it out &lt;a href="http://msdn2.microsoft.com/en-us/vstudio/aa700831.aspx" target="_blank"&gt;here&lt;/a&gt; or &lt;a href="http://blogs.msdn.com/robcaron/archive/2007/07/26/4071925.aspx" target="_blank"&gt;here&lt;/a&gt; (for a download using the Microsoft Secure Content Downloader). I had issues with the last beta when installing on the same machine as VS 2005. The beta caused all sorts of problems with VS 2005 so I recommend installing to a separate box if you can.&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-4134251031648887394&amp;page=RSS%3a+Visual+Studio+2008+Beta+2+Downloads+Available&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=machaira.spaces.live.com&amp;amp;GT1=machaira"&gt;</description><comments>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!370.entry#comment</comments><guid isPermaLink="true">http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!370.entry</guid><pubDate>Fri, 27 Jul 2007 12:09:44 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://machaira.spaces.live.com/blog/cns!C6A0309746469D9E!370/comments/feed.rss</wfw:commentRss><wfw:comment>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!370.entry#comment</wfw:comment><dcterms:modified>2007-07-27T12:09:44Z</dcterms:modified></item><item><title>VS 2008 Beta 2 Coming</title><link>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!366.entry</link><description>&lt;p&gt;From Scott Guthrie's &lt;a href="http://weblogs.asp.net/scottgu/default.aspx" target="_blank"&gt;blog&lt;/a&gt;: &lt;p&gt;&amp;quot;Monday, July 09, 2007 10:30 AM by &lt;a href="http://weblogs.asp.net/user/Profile.aspx?UserID=2530"&gt;ScottGu&lt;/a&gt; &lt;p&gt;Hi Andreas, &lt;p&gt;VS 2008 Beta2 should be available for free download in the next three weeks. It will support a go-live license. &lt;p&gt;Thanks, &lt;p&gt;Scott&amp;quot;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-4134251031648887394&amp;page=RSS%3a+VS+2008+Beta+2+Coming&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=machaira.spaces.live.com&amp;amp;GT1=machaira"&gt;</description><comments>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!366.entry#comment</comments><guid isPermaLink="true">http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!366.entry</guid><pubDate>Wed, 18 Jul 2007 13:23:17 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://machaira.spaces.live.com/blog/cns!C6A0309746469D9E!366/comments/feed.rss</wfw:commentRss><wfw:comment>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!366.entry#comment</wfw:comment><dcterms:modified>2007-07-18T13:23:17Z</dcterms:modified></item><item><title>360 Live API</title><link>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!213.entry</link><description>&lt;div&gt;A post in the MSDN forums led me to a search which pulled up &lt;a href="http://www.xboxusersgroup.com/content/view/3247/217/"&gt;this page&lt;/a&gt;. I didn't know that much of the Live service was exposed for our perusal. If I get a chance, I may experiment with this a bit and post the results here. Please post a comment here if you dig into this and let us know what you've done.&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-4134251031648887394&amp;page=RSS%3a+360+Live+API&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=machaira.spaces.live.com&amp;amp;GT1=machaira"&gt;</description><comments>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!213.entry#comment</comments><guid isPermaLink="true">http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!213.entry</guid><pubDate>Mon, 29 Jan 2007 18:24:51 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://machaira.spaces.live.com/blog/cns!C6A0309746469D9E!213/comments/feed.rss</wfw:commentRss><wfw:comment>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!213.entry#comment</wfw:comment><dcterms:modified>2007-01-29T18:24:51Z</dcterms:modified></item><item><title>C# EE SP1 Beta - come and get it</title><link>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!133.entry</link><description>A new entry on the XNA Team's blog let us know of the download for the beta of SP1 of C# EE. &lt;a href="http://blogs.msdn.com/xna/archive/2006/10/13/try-visual-c-express-sp1-beta.aspx"&gt;Check it out&lt;/a&gt;.&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-4134251031648887394&amp;page=RSS%3a+C%23+EE+SP1+Beta+-+come+and+get+it&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=machaira.spaces.live.com&amp;amp;GT1=machaira"&gt;</description><comments>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!133.entry#comment</comments><guid isPermaLink="true">http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!133.entry</guid><pubDate>Tue, 17 Oct 2006 14:57:59 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://machaira.spaces.live.com/blog/cns!C6A0309746469D9E!133/comments/feed.rss</wfw:commentRss><wfw:comment>http://machaira.spaces.live.com/Blog/cns!C6A0309746469D9E!133.entry#comment</wfw:comment><dcterms:modified>2006-11-10T13:05:59Z</dcterms:modified></item></channel></rss>