Essentially what Aron_dc said, though I would go even farther. Generally you should try to keep your class-structure as shallow as possible and separate code(algorithms) from data(attributes).
You only need one weapon class for melee/instant-hit-weapons. This class can either instantly check what it hit, or is given an object to apply damage to. This includes ranged weapons, that are insta-hit, like a laser (a gun might be too, if you don't want to model it too realistically).
class InstantWeapon{
Sprite sprite; //should be inherited from EquippableObject, or DrawableGameObject, or something
WeaponType weaponType;
DamageType dmgType;
Double dmgOnHit;
...
void Hit(ObjectWithHitPoints o){...}
void Hit(Ray hitRay)
}
A second class is used for particle-spawning weapons, such as a wand of fireball. These weapons don't damage directly, but instead spawn a new object that moves according to its own logic and does damage when it collides with an object. In this case the particle holds all information needed (damage amount and type, radius etc) and it makes it easy to give them custom logic (homing missile, or loosing damage the longer it travels, ...)
class ParticleSpawner{
InteractiveParticle sampleParticle;
void Fire(Vector3 position, Vector3 direction){
ParticleEngine.Add(sampleParticle.Clone());
}
}
Depending on how complex you want your weapon and damage system to be you can have a look at the component pattern. The basic principle is that you would have one Weapon
class and a list with multiple instances of the DamageComponent
class. The DamageComponent
class holds the algorithm and data for all weapon effects that apply to this one weapon.
class Weapon{
List<DamageComponent> damageComponents;
void Fire(Ray hitRay){
foreach(component : DamageComponent)
component.Apply(hitRay);
}
}
Each component can now spawn a fireball, reduce enemy armor, do standard damage, apply an "on fire" effect to targets, etc. Additionally each component can handle the weapon-swing the way it wants. Get only the target directly in front, or cleave in a wide arc, etc...
Also note that the component system can come in handy in other places.
- Different types of armor components protect differently against different damage types
- Particle on update components can influence a single particle in different ways
- Abilities granted by skills or objects only need to be implemented once, since they simply add the can-fly or the can-see-underground component to the player.
Generally it empowers you to create lots of small components that each on their own don't do much, but can form extremely complex systems, since their combinations grow exponentially with each new implementation.
The resulting effects of the system can become quite complex, which is nice, when you want emergent behavior and model things in a complex fashion, but that makes it harder to do things like weapon balance or enemy difficulty. For a popular example, look at Diablo3's with their random ability components. Certain combinations are way stronger than the others.