Genericise spell casting AI class

This commit is contained in:
Electroblob
2018-06-09 17:36:54 +01:00
parent 719c6d5fbb
commit b6400c72a7
6 changed files with 26 additions and 35 deletions
@@ -22,14 +22,14 @@ import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
* Entity AI class for use by instances of {@link ISpellCaster}. This deals with pathing, the spell casting itself and
* the attack cooldown. Also provides an automatic implementation of continuous spell casting using the methods
* specified in {@code ISpellCaster}; all the entity class needs to do is implement those methods.
* @param <T> The type of entity that this AI belongs to; must both extend EntityLiving <i>and</i> implement ISpellCaster
*/
public class EntityAIAttackSpell extends EntityAIBase {
// Mmmm generics...
public class EntityAIAttackSpell<T extends EntityLiving & ISpellCaster> extends EntityAIBase {
/** The entity the AI instance has been applied to. */
private final EntityLiving attacker;
/** The entity the AI instance has been applied to, but as an ISpellCaster. */
private final ISpellCaster caster;
/** The tagret to be attacked. */
/** The entity the AI instance has been applied to. Thanks to type parameters, methods from both EntityLiving and
* ISummonedCreature may be invoked on this field. */
private final T attacker;
private EntityLivingBase target;
/**
* Decremented each tick while greater than 0. When a spell is cast, this is set to that spell's cooldown plus the
@@ -65,23 +65,14 @@ public class EntityAIAttackSpell extends EntityAIBase {
* attacking, and also the amount that is added to the cooldown of the spell that has just been cast.
* @param continuousSpellDuration The number of ticks that continuous spells will be cast for before cooling down.
*/
public EntityAIAttackSpell(ISpellCaster attacker, double speed, float maxDistance, int baseCooldown,
int continuousSpellDuration){
public EntityAIAttackSpell(T attacker, double speed, float maxDistance, int baseCooldown, int continuousSpellDuration){
this.cooldown = -1;
if(!(attacker instanceof EntityLiving)){
throw new IllegalArgumentException(
"Tried to create an EntityAICastSpell for an entity that isn't an EntityLiving");
}else{
this.caster = attacker;
this.attacker = (EntityLiving)attacker;
this.baseCooldown = baseCooldown;
this.continuousSpellDuration = continuousSpellDuration;
this.speed = speed;
this.maxAttackDistance = maxDistance * maxDistance;
this.setMutexBits(3);
}
this.attacker = attacker;
this.baseCooldown = baseCooldown;
this.continuousSpellDuration = continuousSpellDuration;
this.speed = speed;
this.maxAttackDistance = maxDistance * maxDistance;
this.setMutexBits(3);
}
@Override
@@ -112,7 +103,7 @@ public class EntityAIAttackSpell extends EntityAIBase {
}
private void setContinuousSpellAndNotify(Spell spell, SpellModifiers modifiers){
caster.setContinuousSpell(spell);
attacker.setContinuousSpell(spell);
WizardryPacketHandler.net.sendToAllAround(
new PacketNPCCastSpell.Message(attacker.getEntityId(), target == null ? -1 : target.getEntityId(),
EnumHand.MAIN_HAND, spell.id(), modifiers),
@@ -151,11 +142,11 @@ public class EntityAIAttackSpell extends EntityAIBase {
if(distanceSq > (double)this.maxAttackDistance || !targetIsVisible
// ...or the spell is cancelled via events...
|| MinecraftForge.EVENT_BUS
.post(new SpellCastEvent.Tick(attacker, caster.getContinuousSpell(), caster.getModifiers(),
.post(new SpellCastEvent.Tick(attacker, attacker.getContinuousSpell(), attacker.getModifiers(),
Source.NPC, this.continuousSpellDuration - this.continuousSpellTimer))
// ...or the spell no longer succeeds...
|| !caster.getContinuousSpell().cast(attacker.world, attacker, EnumHand.MAIN_HAND,
this.continuousSpellDuration - this.continuousSpellTimer, target, caster.getModifiers())
|| !attacker.getContinuousSpell().cast(attacker.world, attacker, EnumHand.MAIN_HAND,
this.continuousSpellDuration - this.continuousSpellTimer, target, attacker.getModifiers())
// ...or the time has elapsed...
|| this.continuousSpellTimer == 0){
@@ -167,8 +158,8 @@ public class EntityAIAttackSpell extends EntityAIBase {
}else if(this.continuousSpellDuration - this.continuousSpellTimer == 1){
// On the first tick, if the spell did succeed, fire SpellCastEvent.Post.
MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(attacker, caster.getContinuousSpell(),
caster.getModifiers(), Source.NPC));
MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(attacker, attacker.getContinuousSpell(),
attacker.getModifiers(), Source.NPC));
}
}else if(--this.cooldown == 0){
@@ -180,7 +171,7 @@ public class EntityAIAttackSpell extends EntityAIBase {
double dx = target.posX - attacker.posX;
double dz = target.posZ - attacker.posZ;
List<Spell> spells = new ArrayList<Spell>(caster.getSpells());
List<Spell> spells = new ArrayList<Spell>(attacker.getSpells());
if(spells.size() > 0){
@@ -194,7 +185,7 @@ public class EntityAIAttackSpell extends EntityAIBase {
spell = spells.get(attacker.world.rand.nextInt(spells.size()));
SpellModifiers modifiers = caster.getModifiers();
SpellModifiers modifiers = attacker.getModifiers();
if(spell != null && attemptCastSpell(spell, modifiers)){
// The spell worked, so we're done!
@@ -55,7 +55,7 @@ import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntityAdditionalSpawnData {
private EntityAIAttackSpell spellCastingAI = new EntityAIAttackSpell(this, 0.5D, 14.0F, 30, 50);
private EntityAIAttackSpell<EntityEvilWizard> spellCastingAI = new EntityAIAttackSpell<EntityEvilWizard>(this, 0.5D, 14.0F, 30, 50);
public int textureIndex = 0;
@@ -27,7 +27,7 @@ public class EntityPhoenix extends EntitySummonedCreature implements ISpellCaste
private double AISpeed = 0.5;
// Can attack for 7 seconds, then must cool down for 3.
private EntityAIAttackSpell spellAttackAI = new EntityAIAttackSpell(this, AISpeed, 15f, 60, 140);
private EntityAIAttackSpell<EntityPhoenix> spellAttackAI = new EntityAIAttackSpell<EntityPhoenix>(this, AISpeed, 15f, 60, 140);
private Spell continuousSpell;
@@ -31,7 +31,7 @@ public class EntityShadowWraith extends EntitySummonedCreature implements ISpell
private double AISpeed = 1.0;
private EntityAIAttackSpell spellAttackAI = new EntityAIAttackSpell(this, AISpeed, 15f, 30, 0);
private EntityAIAttackSpell<EntityShadowWraith> spellAttackAI = new EntityAIAttackSpell<EntityShadowWraith>(this, AISpeed, 15f, 30, 0);
private static final List<Spell> attack = Collections.singletonList(Spells.darkness_orb);
@@ -29,7 +29,7 @@ public class EntityStormElemental extends EntitySummonedCreature implements ISpe
private double AISpeed = 1.0;
private EntityAIAttackSpell spellAttackAI = new EntityAIAttackSpell(this, AISpeed, 15f, 30, 0);
private EntityAIAttackSpell<EntityStormElemental> spellAttackAI = new EntityAIAttackSpell<EntityStormElemental>(this, AISpeed, 15f, 30, 0);
private static final List<Spell> attack = Collections.singletonList(Spells.lightning_disc);
@@ -84,7 +84,7 @@ import net.minecraftforge.oredict.OreDictionary;
@Mod.EventBusSubscriber
public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISpellCaster, IEntityAdditionalSpawnData {
private EntityAIAttackSpell spellCastingAI = new EntityAIAttackSpell(this, 0.5D, 14.0F, 30, 50);
private EntityAIAttackSpell<EntityWizard> spellCastingAI = new EntityAIAttackSpell<>(this, 0.5D, 14.0F, 30, 50);
public int textureIndex = 0;