diff --git a/src/main/java/electroblob/wizardry/WizardryEventHandler.java b/src/main/java/electroblob/wizardry/WizardryEventHandler.java index 5437b675..35d8c490 100644 --- a/src/main/java/electroblob/wizardry/WizardryEventHandler.java +++ b/src/main/java/electroblob/wizardry/WizardryEventHandler.java @@ -347,18 +347,21 @@ public final class WizardryEventHandler { Spell spell = ((ISpellCaster)event.getEntity()).getContinuousSpell(); SpellModifiers modifiers = ((ISpellCaster)event.getEntity()).getModifiers(); + int count = ((ISpellCaster)event.getEntity()).getSpellCounter(); if(spell != null && spell != Spells.none){ // IntelliJ is wrong, do NOT remove the null check! if(!MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Tick(SpellCastEvent.Source.NPC, spell, event.getEntityLiving(), - modifiers, 0))){ + modifiers, count))){ - spell.cast(event.getEntity().world, (EntityLiving)event.getEntity(), EnumHand.MAIN_HAND, 0, + spell.cast(event.getEntity().world, (EntityLiving)event.getEntity(), EnumHand.MAIN_HAND, count, // TODO: This implementation of modifiers relies on them being accessible client-side. // Right now that doesn't matter because NPCs don't use modifiers, but they might in future ((EntityLiving)event.getEntity()).getAttackTarget(), modifiers); } } + + ((ISpellCaster)event.getEntity()).setSpellCounter(count + 1); } } } diff --git a/src/main/java/electroblob/wizardry/client/ClientProxy.java b/src/main/java/electroblob/wizardry/client/ClientProxy.java index 30d4e50a..4307ec73 100644 --- a/src/main/java/electroblob/wizardry/client/ClientProxy.java +++ b/src/main/java/electroblob/wizardry/client/ClientProxy.java @@ -434,6 +434,7 @@ public class ClientProxy extends CommonProxy { if(caster instanceof ISpellCaster){ if(spell.isContinuous || spell instanceof None){ ((ISpellCaster)caster).setContinuousSpell(spell); + ((ISpellCaster)caster).setSpellCounter(spell instanceof None ? 0 : 1); ((EntityLiving)caster).setAttackTarget((EntityLivingBase)target); } } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityAIAttackSpell.java b/src/main/java/electroblob/wizardry/entity/living/EntityAIAttackSpell.java index d0cd4c93..21cf3471 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityAIAttackSpell.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityAIAttackSpell.java @@ -213,6 +213,7 @@ public class EntityAIAttackSpell extends return false; } + // This is only called when spell casting starts so ticksInUse is always zero if(spell.cast(attacker.world, attacker, EnumHand.MAIN_HAND, 0, target, modifiers)){ if(spell.isContinuous){ diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityEvilWizard.java b/src/main/java/electroblob/wizardry/entity/living/EntityEvilWizard.java index 1780a3d9..ca20dd61 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityEvilWizard.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityEvilWizard.java @@ -74,6 +74,7 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity // Field implementations private List spells = new ArrayList(4); private Spell continuousSpell; + private int spellCounter; public EntityEvilWizard(World world){ @@ -175,6 +176,16 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity public Spell getContinuousSpell(){ return this.continuousSpell; } + + @Override + public void setSpellCounter(int count){ + spellCounter = count; + } + + @Override + public int getSpellCounter(){ + return spellCounter; + } @Override public int getAimingError(EnumDifficulty difficulty){ diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityPhoenix.java b/src/main/java/electroblob/wizardry/entity/living/EntityPhoenix.java index fbfb9796..23e11730 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityPhoenix.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityPhoenix.java @@ -30,6 +30,7 @@ public class EntityPhoenix extends EntitySummonedCreature implements ISpellCaste private EntityAIAttackSpell spellAttackAI = new EntityAIAttackSpell<>(this, AISpeed, 15f, 60, 140); private Spell continuousSpell; + private int spellCounter; private static final List attack = Collections.singletonList(Spells.flame_ray); @@ -76,6 +77,16 @@ public class EntityPhoenix extends EntitySummonedCreature implements ISpellCaste continuousSpell = spell; } + @Override + public void setSpellCounter(int count){ + spellCounter = count; + } + + @Override + public int getSpellCounter(){ + return spellCounter; + } + @Override public boolean hasRangedAttack(){ return true; diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityShadowWraith.java b/src/main/java/electroblob/wizardry/entity/living/EntityShadowWraith.java index 118a49c0..1ebd82ba 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityShadowWraith.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityShadowWraith.java @@ -61,21 +61,6 @@ public class EntityShadowWraith extends EntitySummonedCreature implements ISpell return attack; } - @Override - public SpellModifiers getModifiers(){ - return new SpellModifiers(); - } - - @Override - public Spell getContinuousSpell(){ - return Spells.none; - } - - @Override - public void setContinuousSpell(Spell spell){ - // Doesn't use continuous spells. - } - @Override protected void applyEntityAttributes(){ super.applyEntityAttributes(); diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityStormElemental.java b/src/main/java/electroblob/wizardry/entity/living/EntityStormElemental.java index ce87a216..ef6c3aee 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityStormElemental.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityStormElemental.java @@ -59,21 +59,6 @@ public class EntityStormElemental extends EntitySummonedCreature implements ISpe return attack; } - @Override - public SpellModifiers getModifiers(){ - return new SpellModifiers(); - } - - @Override - public Spell getContinuousSpell(){ - return Spells.none; - } - - @Override - public void setContinuousSpell(Spell spell){ - // Doesn't use continuous spells. - } - @Override protected void applyEntityAttributes(){ super.applyEntityAttributes(); diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityWizard.java b/src/main/java/electroblob/wizardry/entity/living/EntityWizard.java index cdfac246..4047cf86 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityWizard.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityWizard.java @@ -83,6 +83,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp // Field implementations private List spells = new ArrayList(4); private Spell continuousSpell; + private int spellCounter; /** A set of the positions of the blocks that are part of this wizard's tower. */ private Set towerBlocks; @@ -187,7 +188,17 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp public Spell getContinuousSpell(){ return this.continuousSpell; } - + + @Override + public void setSpellCounter(int count){ + spellCounter = count; + } + + @Override + public int getSpellCounter(){ + return spellCounter; + } + @Override public int getAimingError(EnumDifficulty difficulty){ // Being more intelligent than skeletons, wizards are a little more accurate. diff --git a/src/main/java/electroblob/wizardry/entity/living/ISpellCaster.java b/src/main/java/electroblob/wizardry/entity/living/ISpellCaster.java index 2981d56b..af70b1d1 100644 --- a/src/main/java/electroblob/wizardry/entity/living/ISpellCaster.java +++ b/src/main/java/electroblob/wizardry/entity/living/ISpellCaster.java @@ -19,7 +19,9 @@ import java.util.List; * packets) is handled by that class, and all the implementor needs to do is decide which spell(s) to select. *

* This class also allows Wizardry to do all the syncing necessary for continuous spell casting. All the implementor - * needs to do is store the actual fields involved. + * needs to do is store the actual fields involved, by implementing {@link ISpellCaster#setContinuousSpell(Spell)}, + * {@link ISpellCaster#getContinuousSpell()}, {@link ISpellCaster#setSpellCounter(int)}, {@link ISpellCaster#getSpellCounter()} + * and {@link ISpellCaster#getModifiers()}. */ /* Perhaps this should be a capability? Though I can't help thinking they're mainly for attaching data to vanilla * classes, rather than custom ones. For now, the main purpose of this is to centralise code within wizardry itself, and @@ -39,7 +41,7 @@ public interface ISpellCaster { * list must be castable by NPCs (i.e. {@link Spell#canBeCastBy(net.minecraft.entity.EntityLiving, boolean)} returns true). */ @Nonnull - public List getSpells(); + List getSpells(); /** * Called each time the entity attacks to get the modifiers to apply to the spell. @@ -48,31 +50,47 @@ public interface ISpellCaster { * required, pass in an empty {@code SpellModifiers} object. */ @Nonnull - public SpellModifiers getModifiers(); + default SpellModifiers getModifiers(){ + return new SpellModifiers(); // May seem wasteful but this should never be called so it doesn't matter + } /** * Returns the continuous spell that is currently being cast, or the None spell if there is none. Implementors * should simply store this as a private field and return it here. Will be synced by the AI class, but whether it is - * saved to NBT is up to you. If the implementing class does not deal with continuous spells, just return - * {@link Spells#none}. If the implementing class only ever uses one continuous spell, do not just return - * that spell; the field must still be stored. + * saved to NBT is up to you. If the implementing class only ever uses one continuous spell, do not just + * return that spell; the field must still be stored. */ @Nonnull - public Spell getContinuousSpell(); + default Spell getContinuousSpell(){ + return Spells.none; + } /** * Sets the continuous spell that is currently being cast, or the None spell if there is none. Implementors should * simply store this as a private field and assign it here. Will be synced by the AI class, but whether it is saved * to NBT is up to you. If the implementing class does not deal with continuous spells, leave this method blank. */ - public void setContinuousSpell(Spell spell); + default void setContinuousSpell(Spell spell){ + // Do nothing + } + + /** Returns the number of ticks the current spell has been cast for. Implementors should simply store this as a + * private field and return it here. This is only used client-side. */ + default int getSpellCounter(){ + return 0; + } + + /** Sets the number of ticks the current spell has been cast for. Implementors should simply store this as a + * private field and assign it here. This is only used client-side. */ + default void setSpellCounter(int count){ + // Do nothing + } /** * Returns the aiming error for the given difficulty, used in projectile spells. Defaults to the values used by * skeletons, which are: Easy - 10, Normal - 6, Hard - 2, Peaceful - 10 (rarely used). */ - // This is what default methods are actually intended for! - public default int getAimingError(EnumDifficulty difficulty) { + default int getAimingError(EnumDifficulty difficulty) { return WizardryUtilities.getDefaultAimingError(difficulty); } }