A more efficient approach might be to use Entity Component System or at least borrow the composition design. This allows you to have a single concrete class, say Ability
, that will contain generic fields common to all abilities, e.g. skill points cost, duration of ability, target types, activation types, etc. Then you would have a component for each special value you need to add and a control for each special behavior you need to add to that generic ability. Example:
Ability ability = new Ability();
ability.addComponent(new DurationComponent(double seconds)); // specify how long effect lasts
ability.addControl(new DamagingControl(int damage, Object targetType, etc.)); // so ability can damage
ability.addControl(new ElementAugmentingControl(Element element, Object weapon/armor, etc.)); // so ability can change status effects / elements
This should give you the idea of composition. Based on the common behavior of your abilities, you should end up with about 10-30 classes, while your 400 abilities simply become configurations of the base generic ability. To give you an example here's an RPG with roughly 100 abilities (skills) which are implemented as 6 classes. The same design can also be used with any game items / characters.
As for object creation you can do:
public static final int ABILITY_ID_SOME_NAME = 1000;
ability.addComponent(new IDComponent(ABILITY_ID_SOME_NAME));
Then each of your abilities could be a part of a global data store, where only ability prototypes are stored:
Ability ability = DataStore.getByID(ABILITY_ID_SOME_NAME).clone();
Alternatively, make the data store return an already cloned ability so that you don't expose the prototypes.
Finally, you can consider using a scripting language, e.g. javascript, to change the behavior of the generic ability. In this case all of your abilities would be stored in a folder scripts/abilities/
which you load at runtime and only the ones you need. Some arbitrary example: (heal.js file)
function onUse(object, healValue) {
if (object.hasComponent(HP_COMPONENT)) {
val hp = object.getComponent(HP_COMPONENT);
hp.value += healValue;
}
}
Here's an article that shows how to call javascript functions inside java.