Implement client-side spell counter for NPCs, fixes #345
Also makes all the continuous-spell-related methods in ISpellCaster default methods so they don't need implementing unless actually necessary.
This commit is contained in:
@@ -347,18 +347,21 @@ public final class WizardryEventHandler {
|
|||||||
|
|
||||||
Spell spell = ((ISpellCaster)event.getEntity()).getContinuousSpell();
|
Spell spell = ((ISpellCaster)event.getEntity()).getContinuousSpell();
|
||||||
SpellModifiers modifiers = ((ISpellCaster)event.getEntity()).getModifiers();
|
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(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(),
|
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.
|
// 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
|
// Right now that doesn't matter because NPCs don't use modifiers, but they might in future
|
||||||
((EntityLiving)event.getEntity()).getAttackTarget(), modifiers);
|
((EntityLiving)event.getEntity()).getAttackTarget(), modifiers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
((ISpellCaster)event.getEntity()).setSpellCounter(count + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -434,6 +434,7 @@ public class ClientProxy extends CommonProxy {
|
|||||||
if(caster instanceof ISpellCaster){
|
if(caster instanceof ISpellCaster){
|
||||||
if(spell.isContinuous || spell instanceof None){
|
if(spell.isContinuous || spell instanceof None){
|
||||||
((ISpellCaster)caster).setContinuousSpell(spell);
|
((ISpellCaster)caster).setContinuousSpell(spell);
|
||||||
|
((ISpellCaster)caster).setSpellCounter(spell instanceof None ? 0 : 1);
|
||||||
((EntityLiving)caster).setAttackTarget((EntityLivingBase)target);
|
((EntityLiving)caster).setAttackTarget((EntityLivingBase)target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -213,6 +213,7 @@ public class EntityAIAttackSpell<T extends EntityLiving & ISpellCaster> extends
|
|||||||
return false;
|
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.cast(attacker.world, attacker, EnumHand.MAIN_HAND, 0, target, modifiers)){
|
||||||
|
|
||||||
if(spell.isContinuous){
|
if(spell.isContinuous){
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
|
|||||||
// Field implementations
|
// Field implementations
|
||||||
private List<Spell> spells = new ArrayList<Spell>(4);
|
private List<Spell> spells = new ArrayList<Spell>(4);
|
||||||
private Spell continuousSpell;
|
private Spell continuousSpell;
|
||||||
|
private int spellCounter;
|
||||||
|
|
||||||
public EntityEvilWizard(World world){
|
public EntityEvilWizard(World world){
|
||||||
|
|
||||||
@@ -175,6 +176,16 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
|
|||||||
public Spell getContinuousSpell(){
|
public Spell getContinuousSpell(){
|
||||||
return this.continuousSpell;
|
return this.continuousSpell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSpellCounter(int count){
|
||||||
|
spellCounter = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSpellCounter(){
|
||||||
|
return spellCounter;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAimingError(EnumDifficulty difficulty){
|
public int getAimingError(EnumDifficulty difficulty){
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public class EntityPhoenix extends EntitySummonedCreature implements ISpellCaste
|
|||||||
private EntityAIAttackSpell<EntityPhoenix> spellAttackAI = new EntityAIAttackSpell<>(this, AISpeed, 15f, 60, 140);
|
private EntityAIAttackSpell<EntityPhoenix> spellAttackAI = new EntityAIAttackSpell<>(this, AISpeed, 15f, 60, 140);
|
||||||
|
|
||||||
private Spell continuousSpell;
|
private Spell continuousSpell;
|
||||||
|
private int spellCounter;
|
||||||
|
|
||||||
private static final List<Spell> attack = Collections.singletonList(Spells.flame_ray);
|
private static final List<Spell> attack = Collections.singletonList(Spells.flame_ray);
|
||||||
|
|
||||||
@@ -76,6 +77,16 @@ public class EntityPhoenix extends EntitySummonedCreature implements ISpellCaste
|
|||||||
continuousSpell = spell;
|
continuousSpell = spell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSpellCounter(int count){
|
||||||
|
spellCounter = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSpellCounter(){
|
||||||
|
return spellCounter;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasRangedAttack(){
|
public boolean hasRangedAttack(){
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -61,21 +61,6 @@ public class EntityShadowWraith extends EntitySummonedCreature implements ISpell
|
|||||||
return attack;
|
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
|
@Override
|
||||||
protected void applyEntityAttributes(){
|
protected void applyEntityAttributes(){
|
||||||
super.applyEntityAttributes();
|
super.applyEntityAttributes();
|
||||||
|
|||||||
@@ -59,21 +59,6 @@ public class EntityStormElemental extends EntitySummonedCreature implements ISpe
|
|||||||
return attack;
|
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
|
@Override
|
||||||
protected void applyEntityAttributes(){
|
protected void applyEntityAttributes(){
|
||||||
super.applyEntityAttributes();
|
super.applyEntityAttributes();
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
|||||||
// Field implementations
|
// Field implementations
|
||||||
private List<Spell> spells = new ArrayList<Spell>(4);
|
private List<Spell> spells = new ArrayList<Spell>(4);
|
||||||
private Spell continuousSpell;
|
private Spell continuousSpell;
|
||||||
|
private int spellCounter;
|
||||||
|
|
||||||
/** A set of the positions of the blocks that are part of this wizard's tower. */
|
/** A set of the positions of the blocks that are part of this wizard's tower. */
|
||||||
private Set<BlockPos> towerBlocks;
|
private Set<BlockPos> towerBlocks;
|
||||||
@@ -187,7 +188,17 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
|||||||
public Spell getContinuousSpell(){
|
public Spell getContinuousSpell(){
|
||||||
return this.continuousSpell;
|
return this.continuousSpell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSpellCounter(int count){
|
||||||
|
spellCounter = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSpellCounter(){
|
||||||
|
return spellCounter;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAimingError(EnumDifficulty difficulty){
|
public int getAimingError(EnumDifficulty difficulty){
|
||||||
// Being more intelligent than skeletons, wizards are a little more accurate.
|
// Being more intelligent than skeletons, wizards are a little more accurate.
|
||||||
|
|||||||
@@ -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.
|
* packets) is handled by that class, and all the implementor needs to do is decide which spell(s) to select.
|
||||||
* <p></p>
|
* <p></p>
|
||||||
* This class also allows Wizardry to do all the syncing necessary for continuous spell casting. All the implementor
|
* 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
|
/* 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
|
* 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 <b>must</b> be castable by NPCs (i.e. {@link Spell#canBeCastBy(net.minecraft.entity.EntityLiving, boolean)} returns true).
|
* list <b>must</b> be castable by NPCs (i.e. {@link Spell#canBeCastBy(net.minecraft.entity.EntityLiving, boolean)} returns true).
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public List<Spell> getSpells();
|
List<Spell> getSpells();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called each time the entity attacks to get the modifiers to apply to the spell.
|
* 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.
|
* required, pass in an empty {@code SpellModifiers} object.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@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
|
* 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
|
* 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
|
* saved to NBT is up to you. If the implementing class only ever uses one continuous spell, do <b>not</b> just
|
||||||
* {@link Spells#none}. If the implementing class only ever uses one continuous spell, do <b>not</b> just return
|
* return that spell; the field must still be stored.
|
||||||
* that spell; the field must still be stored.
|
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@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
|
* 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
|
* 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.
|
* 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
|
* 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).
|
* skeletons, which are: Easy - 10, Normal - 6, Hard - 2, Peaceful - 10 (rarely used).
|
||||||
*/
|
*/
|
||||||
// This is what default methods are actually intended for!
|
default int getAimingError(EnumDifficulty difficulty) {
|
||||||
public default int getAimingError(EnumDifficulty difficulty) {
|
|
||||||
return WizardryUtilities.getDefaultAimingError(difficulty);
|
return WizardryUtilities.getDefaultAimingError(difficulty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user