views:

62

answers:

1

In trying to teach myself ASP.NET and OO design in general, I decided to make a simple web-based game. It's a rudimentary role-playing game, where the player can create a character of a certain profession. These professions give the character certain kinds of attacks, and some of these abilities have status effects (poison on enemies, defensive buffs for the character, etc.).

Profession data is stored in XML files. I figured that would be the best way to make it extensible in the future. If I (or anyone else) wanted to add/change professions, all they'd need to do would be to edit or add XML files.

So, with all that said, I've been testing how to successfully extract the various attacks from my professions XML files. Like I said before, some of them have status effects, but not all. Below is a test profession:

<?xml version="1.0" encoding="utf-8" ?>
<CharacterClass>
  <Name>Hacker</Name>
  <InitialStats>
    <HP>10</HP>
    <TP>25</TP>
    <BaseDMG>2</BaseDMG>
    <BaseDefense>25</BaseDefense>
  </InitialStats>
  <LevelingStats>
    <HPMultiplier>2</HPMultiplier>
    <TPMultiplier>4</TPMultiplier>
    <BaseDMGMultiplier>2</BaseDMGMultiplier>
    <DefenseIncrease>5</DefenseIncrease>
  </LevelingStats>
  <Attacks>
    <Attack>
      <AttackName>Basic Attack</AttackName>
      <AttackLevel>1</AttackLevel>
      <TPCost>0</TPCost>
      <DMGModifier>1</DMGModifier>
      <HitPenalty>0</HitPenalty>
      <StatusEffect>
        <Type>null</Type>
        <Duration>0</Duration>
        <Level>0</Level>
      </StatusEffect>
    </Attack>
  </Attacks>
</CharacterClass>

As you can see, each profession confers various attacks, which are objects within my system. Status effects are also objects - in fact, they're Observers that can be attached to characters.

My problem stems from attacks that don't have status effects, like the Basic Attack shown above. I have a partial solution, but it seems inelegant:

public partial class xmltest : System.Web.UI.Page
{
    public StatusEffect CreateStatusEffect(XElement se)
    {
        if (se.Element("Type") != null)
        {
            StatusEffect result = (StatusEffect)Assembly.GetExecutingAssembly().CreateInstance(((string)se.Element("Type")));
            result.Name = (string)se.Element("Name");
            result.Duration = (int)se.Element("Duration");
            result.Level = (int)se.Element("Level");

            return result;
        }
        else
        {
            throw new Exception();
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        List<Attack> charAttacks = (from a in XElement.Load(MapPath("CharacterClasses/Hacker.xml")).Element("Attacks").Elements("Attack")
                                    let se = a.Element("StatusEffect")
                                    select new Attack
                                    (
                                        (string)a.Element("AttackName"),
                                        (int)a.Element("AttackLevel"),
                                        (int)a.Element("TPCost"),
                                        (double)a.Element("DMGModifier"),
                                        (double)a.Element("HitPenalty"),
                                        CreateStatusEffect(se)
                                    )).ToList();


        foreach (Attack attack in charAttacks)
        {
            output.InnerHtml = attack.Name + "<br />";
        }
    }
}

Is it possible for me to:

  1. Check for the existence of a status effect
  2. Build it if it exists

Within the LINQ query itself? Playing with the current executing assembly registers as a bad code smell for me. I'm sure I'm missing something obvious.

+1  A: 

Try this out

XDocument doc = XDocument.Load( MapPath("CharacterClasses/Hacker.xml"));   
List<Attack> charAttacks = (from attack in doc.Descendants("Attack")
                                    select new Attack()
                                    {
                                        AttackName = (string)attack.Element("AttackName") ?? null,
                                        AttackLevel = (int)attack.Element("AttackLevel"),
                                        TPCost = (int)attack.Element("TPCost"),
                                        DMGModifier = (double)attack.Element("DMGModifier"),
                                        HitPenalty = (double)attack.Element("HitPenalty"),
                                        StatusEffect = attack.Element("StatusEffect") == null ? null :
                                                              new StatusEffect()
                                                              {
                                                                  Name = (string)attack.Element("StatusEffect").Element("Name"),
                                                                  Duration = (int)attack.Element("StatusEffect").Element("Duration"),
                                                                  Level = (int)attack.Element("StatusEffect").Element("Level")
                                                              }
                                    }).ToList();`enter code here`

The Class definitions for Attack and StatusEffect need to have public properties as shown below for the above linq statement to work

class Attack
    {
        public string AttackName { get; set; }
        public int AttackLevel { get; set; }
        public int TPCost { get; set; }
        public double DMGModifier { get; set; }
        public double HitPenalty { get; set; }
        public StatusEffect StatusEffect { get; set; }
    }

    class StatusEffect
    {
        public string Name { get; set; }
        public int Duration { get; set; }
        public int Level { get; set; }
    }
Vinay B R
Exactly what I wanted to know. Thanks!
kevinmajor1