The choices you make in code depend upon what your expectations are for the game.
- How many different skills/items are in your game?
- How much code do they share in common?
- Do they interact with each other?
- How does the player obtain new skills/items?
- How often will you release new skills/items?
- Can users create their own?
Let's say you're creating a single-player game where you expect the player to go through 10 levels and get a new skill at the end of every level. In that case, you don't need a complicated system for managing skills. You could simply create a new class for each skill and hard code specific methods for each skill (e.g. Shoot()
, Summon()
, SetOnFire()
).
On the other hand, let's say you're creating a multiplayer game with a release cycle of a new skill every week, and you expect to have hundreds of skills. In that case, you need an easy way to deliver new skill definitions to players, so XML or some binary format makes sense. Additionally, skills will likely share a lot of features, so a component-based entity system makes sense.
The same logic applies for your question about the fireball skill and particle system. Is the fireball skill the only class that will be using particles? In that case, just hard code the relationship. If many skills will be using particles, then you may want to use a message passing system, so that any entity can request a particle to be created without needing a reference to the actual particle system object. You could use dependency injection if you expect to have multiple types of particle systems.
There's no correct answer to code architecture, just a bunch of tradeoffs that you decide upon that best fits your game and development team.