Capacités - HelmDefense/HelmDefense GitHub Wiki

Le système des capacités

Présentation du système

Les différentes entités (attaquants, défenseurs et projectiles) peuvent avoir des capacités. En effet, ils possèdent un attribut List<Ability> qui dépend de leur nature et de quelques autres éléments. Ces Ability sont enregistrées comme écouteurs des actions (pour les GameAction) et sont utilisées pour déclencher les EntityAction.

Les capacités définies dans le package fr.helmdefense.model.entitites.abilities.list peuvent être attribuées aux entités à travers leur définition dans le fichier game_data/entities.yml. Il est cependant important de noter que des capacités peuvent se situer en dehors de ce package, mais elle ne pourrons alors pas être donnée dans le yml des entités. Ces dernières possèdent ainsi une méthode addAbilities(Ability... abilities) qui permet d'ajouter des capacités dynamiquement à une entité.

Notre utilisation

Pour pouvoir utiliser des capacités et les donner aux entités, il faut d'abord les créer.

Les capacités

Présentation

Une capacité est une classe qui hérite de la classe abstraite Ability. Par convention, on suffixera toujours le nom d'une capacité par le mot Ability. Pour être utilisée dans le yml, la signature de son / ses constructeur(s) doit impérativement commencer par le tier de déverrouillage et la spécification nécessaire, et les types doivent absolument être des objets (pas de type primitifs) :

public class ExampleAbility extends Ability {
	public ExampleAbility(Tier unlock, Tier.Specification tierSpecification, Integer someDuration, String randomParameter/*, etc... */) {
		super(unlock, tierSpecification);
		// Do some stuff with parameters...
	}
}

La classe Ability implémente l'interface ActionListener. En effet, les capacités ne peuvent être déclenchées que par des Action. La convention de nommage est méthodes annotés @ActionHandler des capacités est soit de réécrire le nom de l'Action (sans le mot Action à la fin) précédé d'un on, soit de donner un nom cohérent avec le comportement de la méthode dans cette capacité.

Exemples

Voici deux exemples de capacités bien différents : Le premier est une capacité "standard" pouvant être attribuée dans le yml et la seconde une capacité "particulière" ayant pour but de compter les entités d'une vague.

public class MultishotAbility extends Ability {
	private double angle;
	private boolean shooting;
	
	public MultishotAbility(Tier unlock, Tier.Specification tierSpecification) {
		this(unlock, tierSpecification, 15d);
	}
	
	public MultishotAbility(Tier unlock, Tier.Specification tierSpecification, Double angle) {
		super(unlock, tierSpecification);
		this.angle = angle;
		this.shooting = false;
	}
	
	@ActionHandler
	public void multishotAbility(ProjectileEntityShootAction action) {
		if (this.shooting)
			return;
		
		this.shooting = true;
		Projectile p = action.getEntity();
		new Projectile(p.getType(), p.getSource(), p.getTarget(), this.angle, p.getSpeed()).spawn(p.getSource().getLevel());
		new Projectile(p.getType(), p.getSource(), p.getTarget(), - this.angle, p.getSpeed()).spawn(p.getSource().getLevel());
		this.shooting = false;
	}
}

Exemple d'utilisation : La capacité permettant de tirer 3 flèches en une seule (MultishotAbility)

public class WaveDeathCountAbility extends Ability {
	public WaveDeathCountAbility() {
		super(Tier.DEFAULT, Tier.Specification.DEFAULT);
	}
	
	@ActionHandler
	public void onDeath(LivingEntityDeathAction action) {
		entityCount--;
	}
}

Exemple d'utilisation : Une capacité particulière définie dans les vagues afin de compter les entités

La distribution aux entités

Comme mentionné précédemment, nous utilisons ces capacités pour les donner aux entités. La plupart sont attribuées à travers leur définition dans le yml, mais il y a tout de même quelques exceptions.

Dans le fichier game_data/entities.yml

Toutes les capacités se trouvant dans le bon package et étant définies dans ce fichier peuvent recevoir des paramètres. Ces paramètres devront être passés sous forme de liste à la capacité selon le schéma suivant :

abilities:
  ExampleAbility:
    - Param1 # Param1 should be the ability unlock Tier.
             # If omitted, Tier.DEFAULT is used.
    - Param2 # Param2 should be the tier specification
             # If omitted, Tier.Specification.DEFAULT is used.
    - ...
    - ParamN
  OtherAbility:
    - OtherParam1
    - ...

À travers le code

Il est possible d'attribuer une capacité à travers le code en l'instanciant et en passant l'objet à la méthode addAbilities(Ability... abilities) de l'entité concernée. C'est le cas des vagues qui donnent à leurs entités une capacité leur permettant de comptabiliser leur mort.

Exemples

Voici deux exemples, le premier il s'agit d'une définition "standard" dans le yml, et la deuxième la capacité mentionnée plus haut donnée par les vagues.

Entity entity = new LivingEntity((LivingEntityType) EntityType.getFromName(e.getValue()), 0, 0);
entity.addAbilities(new WaveDeathCountAbility());
return entity;

Exemple d'utilisation : L'attribution de la capacité de comptabilisation de mort aux entités d'une vague (simplifiée)

HUMAN_WARRIOR:
  name: "Guerrier Humain"
  abilities:
    BountyHuntingAbility: []
    DirectAttackAbility: []
    BonusAbility:
      - TIER_3
      - A
      - ATK_RANGE
      - ADD
      - 0.5
    AreaDirectAttackAbility:
      - TIER_3
      - B
      - 0.75
  size:
    width: 0.5
    height: 0.5

Exemple d'utilisation : La définition des guerrier humains dans game_data/entities.yml (simplifiée)

⚠️ **GitHub.com Fallback** ⚠️