Great Question!
In general, you should start with your high level objects and then think about what they do. So, I'm not sure about your specific use case, but I'll assume it is the following:
A player will use a skill to attack a different player. This will only work if that skill can be used on that player, which is dependent on a set of conditions.
In those two sentences, the nouns are "player", "skill", and "condition".
If you already have the player object, then you need to create skill and condition. Then, you need to have player possess a set of skills and a skill posses a set of conditions. Let's start with conditions:
interface condition {
public function isOk(Player $otherPlayer);
}
Then, you can make any condition you want, let's say the one that checks if the player has a shield:
class hasShield implements condition {
public function isOk(Player $otherPlayer) {
return !$otherPlayer.hasShield;
}
}
Now onto skills, skills will need a way to attack another player, so an interface could be:
interface skill {
public function attack(Player $otherPlayer);
}
Then, you could create any skill you wanted, and have it fit this interface:
class basicAttack implements skill {
public function attack(Player $otherPlayer) {
// check conditions
foreach ($conditions as $condition) {
if (! $condtion.isOk($otherPlayer) return;
}
// attack
// do thing to $otherPlayer;
}
}
Finally, you need to add a list of skills in the player object and provide a way for that class to choose and use one of those skills to attack another player.
Hope this helps!