1
\$\begingroup\$

I'm making a FireEmblem style game, and I am working on items at the moment. I have a Weapon class from which Sword, Axe, etc. are derived. I also have character classes like Swordsman, Mage, etc. I would like to have a way to allow classes to only equip certain weapons (Swordsman can equip Sword but not Axe). One way I thought of was to have a global enum for WeaponType, and each weapon has a const weapon_type value. Then, each character class has a list of allowed WeaponTypes and you would check if a weapon's weapon_type is in the allowed list.

Is there a better way to implement this without using any casting?

\$\endgroup\$
5
\$\begingroup\$

Sword, Axe, et cetera as subclasses of Weapon sound like inheritance abuse to me. Fundamentally these types of weapon differ only in data (how much damage they do, what type of damage it is, what sprites or animations or effects are associated with the weapon, and so on). Consequently I'd advocate for an approach where you flatten this hierarchy away, leaving just the Weapon class.

This provides more impetus for your suggested approach of giving weapons a type flag and giving classes a set of types they can legally equip. If you implement this type flag as an enumeration organized like a bitfield

enum WeaponType {
  None = 0,
  Dagger = 1,
  Sword = 2,
  Axe = 4,
  Spear = 8,
  Bow = 16,
  Boomerang = 32,
  Gun = 64,
};

then you can give the CharacterClass type a field called, for example, equippableWeaponMask. This can be a bitwise combination of the weapon type flags that are valid for the class to wear:

CharacterClass warrior;
warrior.equippableWeaponMask = Dagger | Sword | Axe | Spear;

CharacterClass mage;
mage.equippableWeaponMask = Dagger | Gun;

CharacterClass hunter;
hunter.equippableWeaponMask = Spear | Bow | Gun;

Then, the query to see if a character class can equip a certain weapon is:

bool CharacterClass::canEquip (const Weapon & weapon) {
  return (weapon.type & equippableWeaponMask) != 0;
}

Note that this also suggests you don't need distinct subclasses for CharacterClass either, but can also represent their capabilities purely in data.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.