Finish implementing SpellAreaEffect and retrofit various spell classes to extend it
This commit is contained in:
@@ -2,68 +2,55 @@ package electroblob.wizardry.spell;
|
|||||||
|
|
||||||
import electroblob.wizardry.Wizardry;
|
import electroblob.wizardry.Wizardry;
|
||||||
import electroblob.wizardry.constants.Constants;
|
import electroblob.wizardry.constants.Constants;
|
||||||
|
import electroblob.wizardry.entity.living.ISpellCaster;
|
||||||
import electroblob.wizardry.event.SpellCastEvent;
|
import electroblob.wizardry.event.SpellCastEvent;
|
||||||
import electroblob.wizardry.item.SpellActions;
|
import electroblob.wizardry.item.SpellActions;
|
||||||
import electroblob.wizardry.registry.WizardryItems;
|
import electroblob.wizardry.registry.WizardryItems;
|
||||||
import electroblob.wizardry.registry.WizardryPotions;
|
import electroblob.wizardry.registry.WizardryPotions;
|
||||||
import electroblob.wizardry.util.*;
|
import electroblob.wizardry.util.ParticleBuilder;
|
||||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||||
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.potion.PotionEffect;
|
import net.minecraft.potion.PotionEffect;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.util.math.MathHelper;
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
import net.minecraftforge.fml.common.eventhandler.EventPriority;
|
import net.minecraftforge.fml.common.eventhandler.EventPriority;
|
||||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
|
||||||
import java.util.List;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
@Mod.EventBusSubscriber
|
@Mod.EventBusSubscriber
|
||||||
public class EmpoweringPresence extends Spell {
|
public class EmpoweringPresence extends SpellAreaEffect {
|
||||||
|
|
||||||
public EmpoweringPresence(){
|
public EmpoweringPresence(){
|
||||||
super("empowering_presence", SpellActions.POINT_UP, false);
|
super("empowering_presence", SpellActions.POINT_UP, false);
|
||||||
addProperties(EFFECT_RADIUS, EFFECT_DURATION, EFFECT_STRENGTH);
|
this.alwaysSucceed(true);
|
||||||
|
this.targetAllies(true);
|
||||||
|
addProperties(EFFECT_DURATION, EFFECT_STRENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
protected boolean affectEntity(World world, Vec3d origin, @Nullable EntityLivingBase caster, EntityLivingBase target, int targetCount, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
|
||||||
List<EntityPlayer> targets = EntityUtils.getEntitiesWithinRadius(getProperty(EFFECT_RADIUS).doubleValue()
|
if(target instanceof EntityPlayer || target instanceof ISpellCaster){ // Only useful for spell casters
|
||||||
* modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world, EntityPlayer.class);
|
|
||||||
|
|
||||||
for(EntityPlayer target : targets){
|
int bonusAmplifier = SpellBuff.getStandardBonusAmplifier(modifiers.get(SpellModifiers.POTENCY));
|
||||||
if(AllyDesignationSystem.isPlayerAlly(caster, target) || target == caster){
|
|
||||||
|
|
||||||
int bonusAmplifier = SpellBuff.getStandardBonusAmplifier(modifiers.get(SpellModifiers.POTENCY));
|
target.addPotionEffect(new PotionEffect(WizardryPotions.empowerment,
|
||||||
|
(int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)),
|
||||||
target.addPotionEffect(new PotionEffect(WizardryPotions.empowerment,
|
getProperty(EFFECT_STRENGTH).intValue() + bonusAmplifier));
|
||||||
(int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)),
|
|
||||||
getProperty(EFFECT_STRENGTH).intValue() + bonusAmplifier));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(world.isRemote){
|
|
||||||
|
|
||||||
for(int i = 0; i < 50 * modifiers.get(WizardryItems.blast_upgrade); i++){
|
|
||||||
|
|
||||||
double radius = (1 + world.rand.nextDouble() * 4) * modifiers.get(WizardryItems.blast_upgrade);
|
|
||||||
float angle = world.rand.nextFloat() * (float)Math.PI * 2;
|
|
||||||
|
|
||||||
double x = caster.posX + radius * MathHelper.cos(angle);
|
|
||||||
double y = caster.getEntityBoundingBox().minY;
|
|
||||||
double z = caster.posZ + radius * MathHelper.sin(angle);
|
|
||||||
|
|
||||||
ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.03, 0).time(50).clr(0.5f, 0.4f, 0.75f).spawn(world);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
playSound(world, caster, ticksInUse, -1, modifiers);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void spawnParticle(World world, double x, double y, double z){
|
||||||
|
ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.03, 0).time(50).clr(0.5f, 0.4f, 0.75f).spawn(world);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getTranslationKey(){
|
protected String getTranslationKey(){
|
||||||
return Wizardry.tisTheSeason ? super.getTranslationKey() + "_festive" : super.getTranslationKey();
|
return Wizardry.tisTheSeason ? super.getTranslationKey() + "_festive" : super.getTranslationKey();
|
||||||
|
|||||||
@@ -4,65 +4,49 @@ import electroblob.wizardry.event.SpellCastEvent;
|
|||||||
import electroblob.wizardry.item.SpellActions;
|
import electroblob.wizardry.item.SpellActions;
|
||||||
import electroblob.wizardry.registry.WizardryItems;
|
import electroblob.wizardry.registry.WizardryItems;
|
||||||
import electroblob.wizardry.registry.WizardryPotions;
|
import electroblob.wizardry.registry.WizardryPotions;
|
||||||
import electroblob.wizardry.util.*;
|
import electroblob.wizardry.util.ParticleBuilder;
|
||||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||||
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.potion.PotionEffect;
|
import net.minecraft.potion.PotionEffect;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.util.math.MathHelper;
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.fml.common.eventhandler.EventPriority;
|
import net.minecraftforge.fml.common.eventhandler.EventPriority;
|
||||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
|
||||||
import java.util.List;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class FontOfMana extends Spell {
|
public class FontOfMana extends SpellAreaEffect {
|
||||||
|
|
||||||
public FontOfMana(){
|
public FontOfMana(){
|
||||||
super("font_of_mana", SpellActions.POINT_UP, false);
|
super("font_of_mana", SpellActions.POINT_UP, false);
|
||||||
this.soundValues(0.7f, 1.2f, 0.4f);
|
this.soundValues(0.7f, 1.2f, 0.4f);
|
||||||
addProperties(EFFECT_RADIUS, EFFECT_DURATION, EFFECT_STRENGTH);
|
this.particleDensity(1.25f);
|
||||||
|
this.targetAllies(true);
|
||||||
|
this.alwaysSucceed(true);
|
||||||
|
addProperties(EFFECT_DURATION, EFFECT_STRENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
protected boolean affectEntity(World world, Vec3d origin, @Nullable EntityLivingBase caster, EntityLivingBase target, int targetCount, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
|
||||||
double maxRadius = getProperty(EFFECT_RADIUS).doubleValue();
|
if(target instanceof EntityPlayer){ // Font of mana is only useful to players
|
||||||
|
target.addPotionEffect(new PotionEffect(WizardryPotions.font_of_mana,
|
||||||
List<EntityPlayer> targets = EntityUtils.getEntitiesWithinRadius(
|
(int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)),
|
||||||
maxRadius * modifiers.get(WizardryItems.blast_upgrade),
|
(int)(getProperty(EFFECT_STRENGTH).intValue() + (modifiers.get(SpellModifiers.POTENCY) - 1) * 2)));
|
||||||
caster.posX, caster.posY, caster.posZ, world, EntityPlayer.class);
|
|
||||||
|
|
||||||
for(EntityPlayer target : targets){
|
|
||||||
if(AllyDesignationSystem.isPlayerAlly(caster, target) || target == caster){
|
|
||||||
target.addPotionEffect(new PotionEffect(WizardryPotions.font_of_mana,
|
|
||||||
(int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)),
|
|
||||||
(int)(getProperty(EFFECT_STRENGTH).intValue() + (modifiers.get(SpellModifiers.POTENCY) - 1) * 2)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(world.isRemote){
|
|
||||||
for(int i = 0; i < 100 * modifiers.get(WizardryItems.blast_upgrade); i++){
|
|
||||||
|
|
||||||
double radius = (1 + world.rand.nextDouble() * (maxRadius - 1)) * modifiers.get(WizardryItems.blast_upgrade);
|
|
||||||
float angle = world.rand.nextFloat() * (float)Math.PI * 2;
|
|
||||||
;
|
|
||||||
float hue = world.rand.nextFloat() * 0.4f;
|
|
||||||
|
|
||||||
double x = caster.posX + radius * MathHelper.cos(angle);
|
|
||||||
double y = caster.getEntityBoundingBox().minY;
|
|
||||||
double z = caster.posZ + radius * MathHelper.sin(angle);
|
|
||||||
|
|
||||||
ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.03, 0).time(50)
|
|
||||||
.clr(1, 1 - hue, 0.6f + hue).spawn(world);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
playSound(world, caster, ticksInUse, -1, modifiers);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void spawnParticle(World world, double x, double y, double z){
|
||||||
|
float hue = world.rand.nextFloat() * 0.4f;
|
||||||
|
ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.03, 0).time(50)
|
||||||
|
.clr(1, 1 - hue, 0.6f + hue).spawn(world);
|
||||||
|
}
|
||||||
|
|
||||||
@SubscribeEvent(priority = EventPriority.LOW) // Doesn't really matter but there's no point processing it if casting is blocked
|
@SubscribeEvent(priority = EventPriority.LOW) // Doesn't really matter but there's no point processing it if casting is blocked
|
||||||
public static void onSpellCastPreEvent(SpellCastEvent.Pre event){
|
public static void onSpellCastPreEvent(SpellCastEvent.Pre event){
|
||||||
// Moved from ItemWand (quite why this wasn't done with modifiers before I don't know!)
|
// Moved from ItemWand (quite why this wasn't done with modifiers before I don't know!)
|
||||||
|
|||||||
@@ -8,23 +8,28 @@ import electroblob.wizardry.util.ParticleBuilder.Type;
|
|||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.init.MobEffects;
|
import net.minecraft.init.MobEffects;
|
||||||
import net.minecraft.potion.PotionEffect;
|
import net.minecraft.potion.PotionEffect;
|
||||||
|
import net.minecraft.util.DamageSource;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class ForestsCurse extends SpellAreaEffect {
|
public class ForestsCurse extends SpellAreaEffect {
|
||||||
|
|
||||||
public ForestsCurse(){
|
public ForestsCurse(){
|
||||||
super("forests_curse", SpellActions.POINT_UP);
|
super("forests_curse", SpellActions.POINT_UP, false);
|
||||||
|
this.alwaysSucceed(true);
|
||||||
this.soundValues(1, 1.1f, 0.2f);
|
this.soundValues(1, 1.1f, 0.2f);
|
||||||
addProperties(DAMAGE, EFFECT_DURATION, EFFECT_STRENGTH);
|
addProperties(DAMAGE, EFFECT_DURATION, EFFECT_STRENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void affectEntity(World world, EntityLivingBase caster, EntityLivingBase target, SpellModifiers modifiers){
|
protected boolean affectEntity(World world, Vec3d origin, @Nullable EntityLivingBase caster, EntityLivingBase target, int targetCount, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
|
||||||
if(!MagicDamage.isEntityImmune(DamageType.POISON, target) && EntityUtils.isLiving(target)){
|
if(!MagicDamage.isEntityImmune(DamageType.POISON, target) && EntityUtils.isLiving(target)){
|
||||||
|
|
||||||
target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.POISON),
|
DamageSource source = caster != null ? MagicDamage.causeDirectMagicDamage(caster, DamageType.POISON) : DamageSource.MAGIC;
|
||||||
getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY));
|
target.attackEntityFrom(source, getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY));
|
||||||
|
|
||||||
int bonusAmplifier = SpellBuff.getStandardBonusAmplifier(modifiers.get(SpellModifiers.POTENCY));
|
int bonusAmplifier = SpellBuff.getStandardBonusAmplifier(modifiers.get(SpellModifiers.POTENCY));
|
||||||
int duration = (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade));
|
int duration = (int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade));
|
||||||
@@ -34,6 +39,8 @@ public class ForestsCurse extends SpellAreaEffect {
|
|||||||
target.addPotionEffect(new PotionEffect(MobEffects.SLOWNESS, duration, amplifier));
|
target.addPotionEffect(new PotionEffect(MobEffects.SLOWNESS, duration, amplifier));
|
||||||
target.addPotionEffect(new PotionEffect(MobEffects.WEAKNESS, duration, amplifier));
|
target.addPotionEffect(new PotionEffect(MobEffects.WEAKNESS, duration, amplifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,47 +1,41 @@
|
|||||||
package electroblob.wizardry.spell;
|
package electroblob.wizardry.spell;
|
||||||
|
|
||||||
import electroblob.wizardry.item.SpellActions;
|
import electroblob.wizardry.item.SpellActions;
|
||||||
import electroblob.wizardry.registry.WizardryItems;
|
import electroblob.wizardry.util.ParticleBuilder;
|
||||||
import electroblob.wizardry.util.*;
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.util.EnumHand;
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
import java.util.List;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class GroupHeal extends Spell {
|
public class GroupHeal extends SpellAreaEffect {
|
||||||
|
|
||||||
public GroupHeal(){
|
public GroupHeal(){
|
||||||
super("group_heal", SpellActions.POINT_UP, false);
|
super("group_heal", SpellActions.POINT_UP, false);
|
||||||
this.soundValues(0.7f, 1.2f, 0.4f);
|
this.soundValues(0.7f, 1.2f, 0.4f);
|
||||||
addProperties(EFFECT_RADIUS, HEALTH);
|
this.targetAllies(true);
|
||||||
|
addProperties(HEALTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
protected boolean affectEntity(World world, Vec3d origin, @Nullable EntityLivingBase caster, EntityLivingBase target, int targetCount, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
|
||||||
boolean flag = false;
|
if(target.getHealth() < target.getMaxHealth() && target.getHealth() > 0){
|
||||||
|
|
||||||
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(getProperty(EFFECT_RADIUS).floatValue()
|
Heal.heal(target, getProperty(HEALTH).floatValue() * modifiers.get(SpellModifiers.POTENCY));
|
||||||
* modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world);
|
|
||||||
|
|
||||||
for(EntityLivingBase target : targets){
|
if(world.isRemote) ParticleBuilder.spawnHealParticles(world, target);
|
||||||
|
playSound(world, target, ticksInUse, -1, modifiers);
|
||||||
if(target == caster || AllyDesignationSystem.isAllied(caster, target)){
|
return true;
|
||||||
|
|
||||||
if(target.getHealth() < target.getMaxHealth() && target.getHealth() > 0){
|
|
||||||
|
|
||||||
Heal.heal(target, getProperty(HEALTH).floatValue() * modifiers.get(SpellModifiers.POTENCY));
|
|
||||||
|
|
||||||
if(world.isRemote) ParticleBuilder.spawnHealParticles(world, target);
|
|
||||||
playSound(world, target, ticksInUse, -1, modifiers);
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return flag;
|
return false; // Only succeeds if something was healed
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void spawnParticleEffect(World world, Vec3d origin, double radius, @Nullable EntityLivingBase caster, SpellModifiers modifiers){
|
||||||
|
// We're spawning particles above so don't bother with this method
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,11 @@ import electroblob.wizardry.registry.WizardryBlocks;
|
|||||||
import electroblob.wizardry.registry.WizardryItems;
|
import electroblob.wizardry.registry.WizardryItems;
|
||||||
import electroblob.wizardry.registry.WizardryPotions;
|
import electroblob.wizardry.registry.WizardryPotions;
|
||||||
import electroblob.wizardry.registry.WizardrySounds;
|
import electroblob.wizardry.registry.WizardrySounds;
|
||||||
import electroblob.wizardry.util.*;
|
import electroblob.wizardry.util.BlockUtils;
|
||||||
|
import electroblob.wizardry.util.EntityUtils;
|
||||||
|
import electroblob.wizardry.util.ParticleBuilder;
|
||||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||||
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
import net.minecraft.entity.EntityLiving;
|
import net.minecraft.entity.EntityLiving;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
@@ -15,55 +18,90 @@ import net.minecraft.potion.PotionEffect;
|
|||||||
import net.minecraft.util.EnumFacing;
|
import net.minecraft.util.EnumFacing;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.EnumHand;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
import java.util.List;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class IceAge extends Spell {
|
public class IceAge extends SpellAreaEffect {
|
||||||
|
|
||||||
public static final String FREEZE_DURATION = "freeze_duration";
|
public static final String FREEZE_DURATION = "freeze_duration";
|
||||||
|
|
||||||
public IceAge(){
|
public IceAge(){
|
||||||
super("ice_age", SpellActions.POINT_DOWN, false);
|
super("ice_age", SpellActions.POINT_DOWN, false);
|
||||||
this.soundValues(1.5f, 1.0f, 0);
|
this.soundValues(1.5f, 1.0f, 0);
|
||||||
addProperties(EFFECT_RADIUS, FREEZE_DURATION, EFFECT_DURATION, EFFECT_STRENGTH);
|
this.alwaysSucceed(true);
|
||||||
}
|
addProperties(FREEZE_DURATION, EFFECT_DURATION, EFFECT_STRENGTH);
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean requiresPacket(){
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
freezeNearbyBlocks(world, new Vec3d(caster.posX, caster.getEntityBoundingBox().minY, caster.posZ), caster, modifiers);
|
||||||
|
return super.cast(world, caster, hand, ticksInUse, modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
float radius = getProperty(EFFECT_RADIUS).floatValue() * modifiers.get(WizardryItems.blast_upgrade);
|
@Override
|
||||||
|
public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){
|
||||||
|
freezeNearbyBlocks(world, caster.getPositionVector(), caster, modifiers);
|
||||||
|
return super.cast(world, caster, hand, ticksInUse, target, modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(radius, caster.posX, caster.posY, caster.posZ, world);
|
@Override
|
||||||
|
public boolean cast(World world, double x, double y, double z, EnumFacing direction, int ticksInUse, int duration, SpellModifiers modifiers){
|
||||||
|
freezeNearbyBlocks(world, new Vec3d(x, y, z), null, modifiers);
|
||||||
|
return super.cast(world, x, y, z, direction, ticksInUse, duration, modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
for(EntityLivingBase target : targets){
|
@Override
|
||||||
if(AllyDesignationSystem.isValidTarget(caster, target)){
|
protected boolean affectEntity(World world, Vec3d origin, @Nullable EntityLivingBase caster, EntityLivingBase target, int targetCount, int ticksInUse, SpellModifiers modifiers){
|
||||||
if(!world.isRemote){
|
|
||||||
|
|
||||||
if(target instanceof EntityLiving){
|
if(target instanceof EntityLiving){
|
||||||
if(((BlockStatue)WizardryBlocks.ice_statue).convertToStatue((EntityLiving)target,
|
if(((BlockStatue)WizardryBlocks.ice_statue).convertToStatue((EntityLiving)target,
|
||||||
(int)(getProperty(FREEZE_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)))){
|
(int)(getProperty(FREEZE_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)))){
|
||||||
target.playSound(WizardrySounds.MISC_FREEZE, 1.0F, world.rand.nextFloat() * 0.4F + 0.8F);
|
target.playSound(WizardrySounds.MISC_FREEZE, 1.0F, world.rand.nextFloat() * 0.4F + 0.8F);
|
||||||
}
|
|
||||||
}else if(target instanceof EntityPlayer){
|
|
||||||
target.addPotionEffect(new PotionEffect(WizardryPotions.frost,
|
|
||||||
(int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)),
|
|
||||||
getProperty(EFFECT_STRENGTH).intValue()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}else if(target instanceof EntityPlayer){
|
||||||
|
target.addPotionEffect(new PotionEffect(WizardryPotions.frost,
|
||||||
|
(int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)),
|
||||||
|
getProperty(EFFECT_STRENGTH).intValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void spawnParticleEffect(World world, Vec3d origin, double radius, @Nullable EntityLivingBase caster, SpellModifiers modifiers){
|
||||||
|
|
||||||
|
for(int i=0; i<100; i++){
|
||||||
|
double speed = (world.rand.nextBoolean() ? 1 : -1) * (0.1 + 0.05 * world.rand.nextDouble());
|
||||||
|
ParticleBuilder.create(Type.SNOW)
|
||||||
|
.pos(origin.x, origin.y + world.rand.nextDouble() * 3, origin.z)
|
||||||
|
.vel(0, 0, 0)
|
||||||
|
.scale(2)
|
||||||
|
.spin(world.rand.nextDouble() * (radius - 0.5) + 0.5, speed)
|
||||||
|
.spawn(world);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0; i<60; i++){
|
||||||
|
double speed = (world.rand.nextBoolean() ? 1 : -1) * (0.05 + 0.02 * world.rand.nextDouble());
|
||||||
|
ParticleBuilder.create(Type.CLOUD)
|
||||||
|
.pos(origin.x, origin.y + world.rand.nextDouble() * 2.5, origin.z)
|
||||||
|
.clr(0xffffff)
|
||||||
|
.spin(world.rand.nextDouble() * (radius - 1) + 0.5, speed)
|
||||||
|
.spawn(world);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void freezeNearbyBlocks(World world, Vec3d origin, @Nullable EntityLivingBase caster, SpellModifiers modifiers){
|
||||||
|
|
||||||
if(!world.isRemote && EntityUtils.canDamageBlocks(caster, world)){
|
if(!world.isRemote && EntityUtils.canDamageBlocks(caster, world)){
|
||||||
|
|
||||||
|
double radius = getProperty(EFFECT_RADIUS).floatValue() * modifiers.get(WizardryItems.blast_upgrade);
|
||||||
|
|
||||||
for(int i = -(int)radius; i <= (int)radius; i++){
|
for(int i = -(int)radius; i <= (int)radius; i++){
|
||||||
for(int j = -(int)radius; j <= (int)radius; j++){
|
for(int j = -(int)radius; j <= (int)radius; j++){
|
||||||
|
|
||||||
BlockPos pos = new BlockPos(caster).add(i, 0, j);
|
BlockPos pos = new BlockPos(origin).add(i, 0, j);
|
||||||
|
|
||||||
Integer y = BlockUtils.getNearestSurface(world, new BlockPos(pos), EnumFacing.UP, (int)radius, true, BlockUtils.SurfaceCriteria.SOLID_LIQUID_TO_AIR);
|
Integer y = BlockUtils.getNearestSurface(world, new BlockPos(pos), EnumFacing.UP, (int)radius, true, BlockUtils.SurfaceCriteria.SOLID_LIQUID_TO_AIR);
|
||||||
|
|
||||||
@@ -71,7 +109,7 @@ public class IceAge extends Spell {
|
|||||||
|
|
||||||
pos = new BlockPos(pos.getX(), y, pos.getZ());
|
pos = new BlockPos(pos.getX(), y, pos.getZ());
|
||||||
|
|
||||||
double dist = caster.getDistance(caster.posX + i, y, caster.posZ + j);
|
double dist = origin.distanceTo(new Vec3d(origin.x + i, y, origin.z + j));
|
||||||
|
|
||||||
// Randomised with weighting so that the nearer the block the more likely it is to be snowed.
|
// Randomised with weighting so that the nearer the block the more likely it is to be snowed.
|
||||||
if(y != -1 && world.rand.nextInt((int)(dist * 2) + 1) < radius && dist < radius){
|
if(y != -1 && world.rand.nextInt((int)(dist * 2) + 1) < radius && dist < radius){
|
||||||
@@ -81,31 +119,6 @@ public class IceAge extends Spell {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(world.isRemote){
|
|
||||||
|
|
||||||
for(int i=0; i<100; i++){
|
|
||||||
double speed = (world.rand.nextBoolean() ? 1 : -1) * (0.1 + 0.05 * world.rand.nextDouble());
|
|
||||||
ParticleBuilder.create(Type.SNOW)
|
|
||||||
.pos(caster.posX, caster.getEntityBoundingBox().minY + world.rand.nextDouble() * 3, caster.posZ)
|
|
||||||
.vel(0, 0, 0)
|
|
||||||
.scale(2)
|
|
||||||
.spin(world.rand.nextDouble() * (radius - 0.5) + 0.5, speed)
|
|
||||||
.spawn(world);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i=0; i<60; i++){
|
|
||||||
double speed = (world.rand.nextBoolean() ? 1 : -1) * (0.05 + 0.02 * world.rand.nextDouble());
|
|
||||||
ParticleBuilder.create(Type.CLOUD)
|
|
||||||
.pos(caster.posX, caster.getEntityBoundingBox().minY + world.rand.nextDouble() * 2.5, caster.posZ)
|
|
||||||
.clr(0xffffff)
|
|
||||||
.spin(world.rand.nextDouble() * (radius - 1) + 0.5, speed)
|
|
||||||
.spawn(world);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.playSound(world, caster, ticksInUse, -1, modifiers);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,21 +11,20 @@ import net.minecraft.entity.Entity;
|
|||||||
import net.minecraft.entity.EntityCreature;
|
import net.minecraft.entity.EntityCreature;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.ai.RandomPositionGenerator;
|
import net.minecraft.entity.ai.RandomPositionGenerator;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.pathfinding.PathPoint;
|
import net.minecraft.pathfinding.PathPoint;
|
||||||
import net.minecraft.potion.PotionEffect;
|
import net.minecraft.potion.PotionEffect;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
|
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
|
||||||
import java.util.List;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
@Mod.EventBusSubscriber
|
@Mod.EventBusSubscriber
|
||||||
public class Intimidate extends Spell {
|
public class Intimidate extends SpellAreaEffect {
|
||||||
|
|
||||||
/** The NBT tag name for storing the feared entity's UUID in the target's tag compound. */
|
/** The NBT tag name for storing the feared entity's UUID in the target's tag compound. */
|
||||||
public static final String NBT_KEY = "fearedEntity";
|
public static final String NBT_KEY = "fearedEntity";
|
||||||
@@ -37,44 +36,46 @@ public class Intimidate extends Spell {
|
|||||||
|
|
||||||
public Intimidate(){
|
public Intimidate(){
|
||||||
super("intimidate", SpellActions.SUMMON, false);
|
super("intimidate", SpellActions.SUMMON, false);
|
||||||
addProperties(EFFECT_RADIUS, EFFECT_DURATION, EFFECT_STRENGTH);
|
this.alwaysSucceed(true);
|
||||||
|
addProperties(EFFECT_DURATION, EFFECT_STRENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
public boolean canBeCastBy(TileEntityDispenser dispenser){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(!world.isRemote){
|
@Override
|
||||||
|
protected boolean affectEntity(World world, Vec3d origin, @Nullable EntityLivingBase caster, EntityLivingBase target, int targetCount, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
|
||||||
List<EntityCreature> entities = EntityUtils.getEntitiesWithinRadius(
|
if(caster != null && target instanceof EntityCreature){
|
||||||
getProperty(EFFECT_RADIUS).floatValue() * modifiers.get(WizardryItems.range_upgrade),
|
|
||||||
caster.posX, caster.posY, caster.posZ, world, EntityCreature.class);
|
|
||||||
|
|
||||||
for(EntityCreature target : entities){
|
int bonusAmplifier = SpellBuff.getStandardBonusAmplifier(modifiers.get(SpellModifiers.POTENCY));
|
||||||
// Why do we need this here?
|
|
||||||
//runAway(target, caster);
|
|
||||||
|
|
||||||
int bonusAmplifier = SpellBuff.getStandardBonusAmplifier(modifiers.get(SpellModifiers.POTENCY));
|
NBTTagCompound entityNBT = target.getEntityData();
|
||||||
|
if(entityNBT != null) entityNBT.setUniqueId(NBT_KEY, caster.getUniqueID());
|
||||||
|
|
||||||
NBTTagCompound entityNBT = target.getEntityData();
|
target.addPotionEffect(new PotionEffect(WizardryPotions.fear,
|
||||||
if(entityNBT != null) entityNBT.setUniqueId(NBT_KEY, caster.getUniqueID());
|
(int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)),
|
||||||
|
getProperty(EFFECT_STRENGTH).intValue() + bonusAmplifier));
|
||||||
target.addPotionEffect(new PotionEffect(WizardryPotions.fear,
|
|
||||||
(int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)),
|
|
||||||
getProperty(EFFECT_STRENGTH).intValue() + bonusAmplifier));
|
|
||||||
}
|
|
||||||
|
|
||||||
}else{
|
|
||||||
for(int i = 0; i < 30; i++){
|
|
||||||
double x = caster.posX - 1 + world.rand.nextDouble() * 2;
|
|
||||||
double y = caster.getEntityBoundingBox().minY + 1.5 + world.rand.nextDouble() * 0.5;
|
|
||||||
double z = caster.posZ - 1 + world.rand.nextDouble() * 2;
|
|
||||||
ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0.9f, 0.1f, 0).spawn(world);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.playSound(world, caster, ticksInUse, -1, modifiers);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void spawnParticleEffect(World world, Vec3d origin, double radius, @Nullable EntityLivingBase caster, SpellModifiers modifiers){
|
||||||
|
|
||||||
|
if(caster != null) origin = caster.getPositionEyes(0);
|
||||||
|
|
||||||
|
for(int i = 0; i < 30; i++){
|
||||||
|
double x = origin.x - 1 + world.rand.nextDouble() * 2;
|
||||||
|
double y = origin.y - 0.25 + world.rand.nextDouble() * 0.5;
|
||||||
|
double z = origin.z - 1 + world.rand.nextDouble() * 2;
|
||||||
|
ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0.9f, 0.1f, 0).spawn(world);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds a random position away from the caster and sets the given target's AI path to that location. Defined here
|
* Finds a random position away from the caster and sets the given target's AI path to that location. Defined here
|
||||||
* so it can be used both in the spell itself and in the potion effect (event handler).
|
* so it can be used both in the spell itself and in the potion effect (event handler).
|
||||||
|
|||||||
@@ -3,63 +3,44 @@ package electroblob.wizardry.spell;
|
|||||||
import electroblob.wizardry.Wizardry;
|
import electroblob.wizardry.Wizardry;
|
||||||
import electroblob.wizardry.item.SpellActions;
|
import electroblob.wizardry.item.SpellActions;
|
||||||
import electroblob.wizardry.registry.WizardryItems;
|
import electroblob.wizardry.registry.WizardryItems;
|
||||||
import electroblob.wizardry.util.*;
|
import electroblob.wizardry.util.ParticleBuilder;
|
||||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.init.MobEffects;
|
import net.minecraft.init.MobEffects;
|
||||||
import net.minecraft.potion.PotionEffect;
|
import net.minecraft.potion.PotionEffect;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.util.math.MathHelper;
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
import java.util.List;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class InvigoratingPresence extends Spell {
|
public class InvigoratingPresence extends SpellAreaEffect {
|
||||||
|
|
||||||
public InvigoratingPresence(){
|
public InvigoratingPresence(){
|
||||||
super("invigorating_presence", SpellActions.POINT_UP, false);
|
super("invigorating_presence", SpellActions.POINT_UP, false);
|
||||||
this.soundValues(0.7f, 1.2f, 0.4f);
|
this.soundValues(0.7f, 1.2f, 0.4f);
|
||||||
addProperties(EFFECT_RADIUS, EFFECT_DURATION, EFFECT_STRENGTH);
|
this.alwaysSucceed(true);
|
||||||
|
this.targetAllies(true);
|
||||||
|
addProperties(EFFECT_DURATION, EFFECT_STRENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
protected boolean affectEntity(World world, Vec3d origin, @Nullable EntityLivingBase caster, EntityLivingBase target, int targetCount, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
|
||||||
List<EntityPlayer> targets = EntityUtils.getEntitiesWithinRadius(
|
int bonusAmplifier = SpellBuff.getStandardBonusAmplifier(modifiers.get(SpellModifiers.POTENCY));
|
||||||
getProperty(EFFECT_RADIUS).floatValue() * modifiers.get(WizardryItems.blast_upgrade),
|
|
||||||
caster.posX, caster.posY, caster.posZ, world, EntityPlayer.class);
|
|
||||||
|
|
||||||
for(EntityPlayer target : targets){
|
target.addPotionEffect(new PotionEffect(MobEffects.STRENGTH,
|
||||||
if(AllyDesignationSystem.isPlayerAlly(caster, target) || target == caster){
|
(int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)),
|
||||||
|
getProperty(EFFECT_STRENGTH).intValue() + bonusAmplifier));
|
||||||
|
|
||||||
int bonusAmplifier = SpellBuff.getStandardBonusAmplifier(modifiers.get(SpellModifiers.POTENCY));
|
|
||||||
|
|
||||||
target.addPotionEffect(new PotionEffect(MobEffects.STRENGTH,
|
|
||||||
(int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)),
|
|
||||||
getProperty(EFFECT_STRENGTH).intValue() + bonusAmplifier));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(world.isRemote){
|
|
||||||
|
|
||||||
for(int i = 0; i < 50 * modifiers.get(WizardryItems.blast_upgrade); i++){
|
|
||||||
|
|
||||||
double radius = (1 + world.rand.nextDouble() * 4) * modifiers.get(WizardryItems.blast_upgrade);
|
|
||||||
float angle = world.rand.nextFloat() * (float)Math.PI * 2;;
|
|
||||||
|
|
||||||
double x = caster.posX + radius * MathHelper.cos(angle);
|
|
||||||
double y = caster.getEntityBoundingBox().minY;
|
|
||||||
double z = caster.posZ + radius * MathHelper.sin(angle);
|
|
||||||
|
|
||||||
ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.03, 0).time(50).clr(1, 0.2f, 0.2f).spawn(world);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
playSound(world, caster, ticksInUse, -1, modifiers);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void spawnParticle(World world, double x, double y, double z){
|
||||||
|
ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.03, 0).time(50).clr(1, 0.2f, 0.2f).spawn(world);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getTranslationKey(){
|
protected String getTranslationKey(){
|
||||||
return Wizardry.tisTheSeason ? super.getTranslationKey() + "_festive" : super.getTranslationKey();
|
return Wizardry.tisTheSeason ? super.getTranslationKey() + "_festive" : super.getTranslationKey();
|
||||||
|
|||||||
@@ -2,82 +2,75 @@ package electroblob.wizardry.spell;
|
|||||||
|
|
||||||
import electroblob.wizardry.item.SpellActions;
|
import electroblob.wizardry.item.SpellActions;
|
||||||
import electroblob.wizardry.registry.WizardryItems;
|
import electroblob.wizardry.registry.WizardryItems;
|
||||||
import electroblob.wizardry.util.*;
|
import electroblob.wizardry.util.MagicDamage;
|
||||||
import electroblob.wizardry.util.MagicDamage.DamageType;
|
import electroblob.wizardry.util.MagicDamage.DamageType;
|
||||||
|
import electroblob.wizardry.util.ParticleBuilder;
|
||||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||||
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.state.IBlockState;
|
import net.minecraft.block.state.IBlockState;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
|
||||||
import net.minecraft.init.MobEffects;
|
import net.minecraft.init.MobEffects;
|
||||||
import net.minecraft.potion.PotionEffect;
|
import net.minecraft.potion.PotionEffect;
|
||||||
import net.minecraft.util.EnumHand;
|
|
||||||
import net.minecraft.util.EnumParticleTypes;
|
import net.minecraft.util.EnumParticleTypes;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
import java.util.List;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class PlagueOfDarkness extends Spell {
|
public class PlagueOfDarkness extends SpellAreaEffect {
|
||||||
|
|
||||||
public PlagueOfDarkness(){
|
public PlagueOfDarkness(){
|
||||||
super("plague_of_darkness", SpellActions.POINT_DOWN, false);
|
super("plague_of_darkness", SpellActions.POINT_DOWN, false);
|
||||||
addProperties(EFFECT_RADIUS, DAMAGE, EFFECT_DURATION, EFFECT_STRENGTH);
|
this.alwaysSucceed(true);
|
||||||
|
addProperties(DAMAGE, EFFECT_DURATION, EFFECT_STRENGTH);
|
||||||
soundValues(1, 1.1f, 0.2f);
|
soundValues(1, 1.1f, 0.2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
protected boolean affectEntity(World world, Vec3d origin, @Nullable EntityLivingBase caster, EntityLivingBase target, int targetCount, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
|
||||||
double radius = getProperty(EFFECT_RADIUS).floatValue() * modifiers.get(WizardryItems.blast_upgrade);
|
if(!MagicDamage.isEntityImmune(DamageType.WITHER, target)){
|
||||||
|
target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.WITHER),
|
||||||
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(radius, caster.posX, caster.posY, caster.posZ, world);
|
getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY));
|
||||||
|
target.addPotionEffect(new PotionEffect(MobEffects.WITHER,
|
||||||
for(EntityLivingBase target : targets){
|
(int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)),
|
||||||
if(AllyDesignationSystem.isValidTarget(caster, target)
|
getProperty(EFFECT_STRENGTH).intValue() + SpellBuff.getStandardBonusAmplifier(modifiers.get(SpellModifiers.POTENCY))));
|
||||||
&& !MagicDamage.isEntityImmune(DamageType.WITHER, target)){
|
|
||||||
target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.WITHER),
|
|
||||||
getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY));
|
|
||||||
target.addPotionEffect(new PotionEffect(MobEffects.WITHER,
|
|
||||||
(int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)),
|
|
||||||
getProperty(EFFECT_STRENGTH).intValue() + SpellBuff.getStandardBonusAmplifier(modifiers.get(SpellModifiers.POTENCY))));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(world.isRemote){
|
|
||||||
|
|
||||||
double particleX, particleZ;
|
|
||||||
|
|
||||||
for(int i = 0; i < 40 * modifiers.get(WizardryItems.blast_upgrade); i++){
|
|
||||||
|
|
||||||
particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble();
|
|
||||||
particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble();
|
|
||||||
ParticleBuilder.create(Type.DARK_MAGIC).pos(particleX, caster.getEntityBoundingBox().minY, particleZ)
|
|
||||||
.vel(particleX - caster.posX, 0, particleZ - caster.posZ).clr(0.1f, 0, 0).spawn(world);
|
|
||||||
|
|
||||||
particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble();
|
|
||||||
particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble();
|
|
||||||
ParticleBuilder.create(Type.SPARKLE).pos(particleX, caster.getEntityBoundingBox().minY, particleZ)
|
|
||||||
.vel(particleX - caster.posX, 0, particleZ - caster.posZ).time(30).clr(0.1f, 0, 0.05f).spawn(world);
|
|
||||||
|
|
||||||
particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble();
|
|
||||||
particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble();
|
|
||||||
IBlockState block = BlockUtils.getBlockEntityIsStandingOn(caster);
|
|
||||||
|
|
||||||
if(block != null){
|
|
||||||
world.spawnParticle(EnumParticleTypes.BLOCK_DUST, particleX, caster.getEntityBoundingBox().minY,
|
|
||||||
particleZ, particleX - caster.posX, 0, particleZ - caster.posZ, Block.getStateId(block));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ParticleBuilder.create(Type.SPHERE)
|
|
||||||
.pos(caster.posX, caster.getEntityBoundingBox().minY + 0.1, caster.posZ)
|
|
||||||
.scale((float)radius * 0.8f)
|
|
||||||
.clr(0.8f, 0, 0.05f)
|
|
||||||
.spawn(world);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.playSound(world, caster, ticksInUse, -1, modifiers);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void spawnParticleEffect(World world, Vec3d origin, double radius, @Nullable EntityLivingBase caster, SpellModifiers modifiers){
|
||||||
|
|
||||||
|
double particleX, particleZ;
|
||||||
|
|
||||||
|
for(int i = 0; i < 40 * modifiers.get(WizardryItems.blast_upgrade); i++){
|
||||||
|
|
||||||
|
particleX = origin.x - 1.0d + 2 * world.rand.nextDouble();
|
||||||
|
particleZ = origin.z - 1.0d + 2 * world.rand.nextDouble();
|
||||||
|
ParticleBuilder.create(Type.DARK_MAGIC).pos(particleX, origin.y, particleZ)
|
||||||
|
.vel(particleX - origin.x, 0, particleZ - origin.z).clr(0.1f, 0, 0).spawn(world);
|
||||||
|
|
||||||
|
particleX = origin.x - 1.0d + 2 * world.rand.nextDouble();
|
||||||
|
particleZ = origin.z - 1.0d + 2 * world.rand.nextDouble();
|
||||||
|
ParticleBuilder.create(Type.SPARKLE).pos(particleX, origin.y, particleZ)
|
||||||
|
.vel(particleX - origin.x, 0, particleZ - origin.z).time(30).clr(0.1f, 0, 0.05f).spawn(world);
|
||||||
|
|
||||||
|
particleX = origin.x - 1.0d + 2 * world.rand.nextDouble();
|
||||||
|
particleZ = origin.z - 1.0d + 2 * world.rand.nextDouble();
|
||||||
|
|
||||||
|
IBlockState block = world.getBlockState(new BlockPos(origin.x, origin.y - 0.5, origin.z));
|
||||||
|
|
||||||
|
if(block != null){
|
||||||
|
world.spawnParticle(EnumParticleTypes.BLOCK_DUST, particleX, origin.y,
|
||||||
|
particleZ, particleX - origin.x, 0, particleZ - origin.z, Block.getStateId(block));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ParticleBuilder.create(Type.SPHERE).pos(origin.add(0, 0.1, 0)).scale((float)radius * 0.8f).clr(0.8f, 0, 0.05f).spawn(world);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,23 +4,27 @@ import electroblob.wizardry.Wizardry;
|
|||||||
import electroblob.wizardry.item.ItemArtefact;
|
import electroblob.wizardry.item.ItemArtefact;
|
||||||
import electroblob.wizardry.item.SpellActions;
|
import electroblob.wizardry.item.SpellActions;
|
||||||
import electroblob.wizardry.registry.WizardryItems;
|
import electroblob.wizardry.registry.WizardryItems;
|
||||||
import electroblob.wizardry.util.*;
|
import electroblob.wizardry.util.EntityUtils;
|
||||||
|
import electroblob.wizardry.util.MagicDamage;
|
||||||
import electroblob.wizardry.util.MagicDamage.DamageType;
|
import electroblob.wizardry.util.MagicDamage.DamageType;
|
||||||
|
import electroblob.wizardry.util.ParticleBuilder;
|
||||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||||
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.state.IBlockState;
|
import net.minecraft.block.state.IBlockState;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.entity.player.EntityPlayerMP;
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
import net.minecraft.network.play.server.SPacketEntityVelocity;
|
import net.minecraft.network.play.server.SPacketEntityVelocity;
|
||||||
import net.minecraft.util.EnumHand;
|
|
||||||
import net.minecraft.util.EnumParticleTypes;
|
import net.minecraft.util.EnumParticleTypes;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.util.text.TextComponentTranslation;
|
import net.minecraft.util.text.TextComponentTranslation;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
import java.util.List;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class Shockwave extends Spell {
|
public class Shockwave extends SpellAreaEffect {
|
||||||
|
|
||||||
public static final String MAX_REPULSION_VELOCITY = "max_repulsion_velocity";
|
public static final String MAX_REPULSION_VELOCITY = "max_repulsion_velocity";
|
||||||
/** The radius within which maximum damage is dealt and maximum repulsion velocity is applied. */
|
/** The radius within which maximum damage is dealt and maximum repulsion velocity is applied. */
|
||||||
@@ -29,104 +33,83 @@ public class Shockwave extends Spell {
|
|||||||
public Shockwave(){
|
public Shockwave(){
|
||||||
super("shockwave", SpellActions.POINT_DOWN, false);
|
super("shockwave", SpellActions.POINT_DOWN, false);
|
||||||
this.soundValues(2, 0.5f, 0);
|
this.soundValues(2, 0.5f, 0);
|
||||||
addProperties(BLAST_RADIUS, DAMAGE, MAX_REPULSION_VELOCITY);
|
addProperties(DAMAGE, MAX_REPULSION_VELOCITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
protected boolean affectEntity(World world, Vec3d origin, @Nullable EntityLivingBase caster, EntityLivingBase target, int targetCount, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
|
||||||
double radius = getProperty(BLAST_RADIUS).floatValue() * modifiers.get(WizardryItems.blast_upgrade);
|
float radius = getProperty(EFFECT_RADIUS).floatValue() * modifiers.get(WizardryItems.blast_upgrade);
|
||||||
|
|
||||||
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(radius, caster.posX, caster.posY, caster.posZ, world);
|
if(target instanceof EntityPlayer){
|
||||||
|
|
||||||
for(EntityLivingBase target : targets){
|
if(!Wizardry.settings.playersMoveEachOther) return false;
|
||||||
|
|
||||||
if(target instanceof EntityPlayer){
|
if(ItemArtefact.isArtefactActive((EntityPlayer)target, WizardryItems.amulet_anchoring)){
|
||||||
|
if(!world.isRemote && caster instanceof EntityPlayer) ((EntityPlayer)caster).sendStatusMessage(
|
||||||
Wizardry.proxy.shakeScreen((EntityPlayer)target, 10);
|
new TextComponentTranslation("spell.resist", target.getName(),
|
||||||
|
this.getNameForTranslationFormatted()), true);
|
||||||
if(!Wizardry.settings.playersMoveEachOther) continue;
|
return false;
|
||||||
|
|
||||||
if(ItemArtefact.isArtefactActive((EntityPlayer)target, WizardryItems.amulet_anchoring)){
|
|
||||||
if(!world.isRemote) caster.sendStatusMessage(new TextComponentTranslation("spell.resist",
|
|
||||||
target.getName(), this.getNameForTranslationFormatted()), true);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(AllyDesignationSystem.isValidTarget(caster, target)){
|
|
||||||
|
|
||||||
// Produces a linear profile from 0 at the edge of the radius to 1 at the epicentre radius, then
|
|
||||||
// a constant value of 1 within the epicentre radius.
|
|
||||||
float proximity = (float)(1 - (Math.max(target.getDistance(caster) - EPICENTRE_RADIUS, 0))/(radius - EPICENTRE_RADIUS));
|
|
||||||
|
|
||||||
// Damage increases closer to player up to a maximum of 4 hearts (at 1 block distance).
|
|
||||||
target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.BLAST),
|
|
||||||
getProperty(DAMAGE).floatValue() * proximity * modifiers.get(SpellModifiers.POTENCY));
|
|
||||||
|
|
||||||
if(!world.isRemote){
|
|
||||||
|
|
||||||
// Entity speed increases closer to the player to a maximum of 3 (at 1 block distance).
|
|
||||||
// This is the entity's speed compared to its distance from the player. Used for a similar triangles
|
|
||||||
// based x, y and z speed calculation.
|
|
||||||
double velocityFactor = proximity * getProperty(MAX_REPULSION_VELOCITY).floatValue();
|
|
||||||
|
|
||||||
double dx = target.posX - caster.posX;
|
|
||||||
double dy = target.getEntityBoundingBox().minY + 1 - caster.posY;
|
|
||||||
double dz = target.posZ - caster.posZ;
|
|
||||||
|
|
||||||
target.motionX = velocityFactor * dx;
|
|
||||||
target.motionY = velocityFactor * dy;
|
|
||||||
target.motionZ = velocityFactor * dz;
|
|
||||||
|
|
||||||
// Player motion is handled on that player's client so needs packets
|
|
||||||
if(target instanceof EntityPlayerMP){
|
|
||||||
((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(world.isRemote){
|
// Produces a linear profile from 0 at the edge of the radius to 1 at the epicentre radius, then
|
||||||
|
// a constant value of 1 within the epicentre radius.
|
||||||
|
float proximity = (float)(1 - (Math.max(origin.distanceTo(target.getPositionVector()) - EPICENTRE_RADIUS, 0))/(radius - EPICENTRE_RADIUS));
|
||||||
|
|
||||||
double particleX, particleZ;
|
// Damage increases closer to player up to a maximum of 4 hearts (at 1 block distance).
|
||||||
|
target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.BLAST),
|
||||||
|
getProperty(DAMAGE).floatValue() * proximity * modifiers.get(SpellModifiers.POTENCY));
|
||||||
|
|
||||||
for(int i = 0; i < 40; i++){
|
if(!world.isRemote){
|
||||||
|
|
||||||
// particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble();
|
// Entity speed increases closer to the player to a maximum of 3 (at 1 block distance).
|
||||||
// particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble();
|
// This is the entity's speed compared to its distance from the player. Used for a similar triangles
|
||||||
// ParticleBuilder.create(Type.SPARKLE).pos(particleX, caster.getEntityBoundingBox().minY, particleZ)
|
// based x, y and z speed calculation.
|
||||||
// .vel(particleX - caster.posX, 0, particleZ - caster.posZ).time(30).clr(0.8f, 0.8f, 1).spawn(world);
|
double velocityFactor = proximity * getProperty(MAX_REPULSION_VELOCITY).floatValue();
|
||||||
//
|
|
||||||
// particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble();
|
|
||||||
// particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble();
|
|
||||||
// ParticleBuilder.create(Type.SPARKLE).pos(particleX, caster.getEntityBoundingBox().minY, particleZ)
|
|
||||||
// .vel(particleX - caster.posX, 0, particleZ - caster.posZ).time(30).clr(0.9f, 0.9f, 0.9f).spawn(world);
|
|
||||||
|
|
||||||
particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble();
|
double dx = target.posX - origin.x;
|
||||||
particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble();
|
double dy = target.getEntityBoundingBox().minY + 1 - origin.y;
|
||||||
IBlockState block = BlockUtils.getBlockEntityIsStandingOn(caster);
|
double dz = target.posZ - origin.z;
|
||||||
|
|
||||||
if(block != null){
|
target.motionX = velocityFactor * dx;
|
||||||
world.spawnParticle(EnumParticleTypes.BLOCK_DUST, particleX, caster.getEntityBoundingBox().minY,
|
target.motionY = velocityFactor * dy;
|
||||||
particleZ, particleX - caster.posX, 0, particleZ - caster.posZ, Block.getStateId(block));
|
target.motionZ = velocityFactor * dz;
|
||||||
}
|
|
||||||
|
// Player motion is handled on that player's client so needs packets
|
||||||
|
if(target instanceof EntityPlayerMP){
|
||||||
|
((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target));
|
||||||
}
|
}
|
||||||
|
|
||||||
ParticleBuilder.create(Type.SPHERE)
|
|
||||||
.pos(caster.posX, caster.getEntityBoundingBox().minY + 0.1, caster.posZ)
|
|
||||||
.scale((float)radius * 0.8f)
|
|
||||||
.clr(0.8f, 0.9f, 1)
|
|
||||||
.spawn(world);
|
|
||||||
|
|
||||||
world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, caster.posX,
|
|
||||||
caster.getEntityBoundingBox().minY + 0.1, caster.posZ, 0, 0, 0);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
caster.swingArm(hand);
|
|
||||||
playSound(world, caster, ticksInUse, -1, modifiers);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void spawnParticleEffect(World world, Vec3d origin, double radius, @Nullable EntityLivingBase caster, SpellModifiers modifiers){
|
||||||
|
|
||||||
|
// Can't put this in affectEntity(...) because it's only called for non-allies, plus here is client-side already
|
||||||
|
EntityUtils.getEntitiesWithinRadius(radius, origin.x, origin.y, origin.z, world, EntityPlayer.class)
|
||||||
|
.forEach(p -> Wizardry.proxy.shakeScreen(p, 10));
|
||||||
|
|
||||||
|
double particleX, particleZ;
|
||||||
|
|
||||||
|
for(int i = 0; i < 40; i++){
|
||||||
|
|
||||||
|
particleX = origin.x - 1.0d + 2 * world.rand.nextDouble();
|
||||||
|
particleZ = origin.z - 1.0d + 2 * world.rand.nextDouble();
|
||||||
|
|
||||||
|
IBlockState block = world.getBlockState(new BlockPos(origin.x, origin.y - 0.5, origin.z));
|
||||||
|
|
||||||
|
if(block != null){
|
||||||
|
world.spawnParticle(EnumParticleTypes.BLOCK_DUST, particleX, origin.y,
|
||||||
|
particleZ, particleX - origin.x, 0, particleZ - origin.z, Block.getStateId(block));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ParticleBuilder.create(Type.SPHERE).pos(origin.add(0, 0.1, 0)).scale((float)radius * 0.8f).clr(0.8f, 0.9f, 1).spawn(world);
|
||||||
|
|
||||||
|
world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, origin.x, origin.y + 0.1, origin.z, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,31 +5,86 @@ import electroblob.wizardry.registry.WizardryItems;
|
|||||||
import electroblob.wizardry.util.AllyDesignationSystem;
|
import electroblob.wizardry.util.AllyDesignationSystem;
|
||||||
import electroblob.wizardry.util.EntityUtils;
|
import electroblob.wizardry.util.EntityUtils;
|
||||||
import electroblob.wizardry.util.SpellModifiers;
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
|
import net.minecraft.entity.EntityLiving;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.item.EnumAction;
|
import net.minecraft.item.EnumAction;
|
||||||
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
|
import net.minecraft.util.EnumFacing;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.EnumHand;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** [NYI] */
|
/**
|
||||||
|
* Generic superclass for all spells which affect entities in a radius around the caster. This allows all
|
||||||
|
* the relevant code to be centralised. This class differs from most other spell superclasses in that it is abstract
|
||||||
|
* and as such must be subclassed to define what the spell actually does. This is because spells of this kind do a wider
|
||||||
|
* variety of different things, so it does not make sense to define more specific functions in this class since they
|
||||||
|
* would be redundant in the majority of cases.
|
||||||
|
* <p></p>
|
||||||
|
* <i>N.B. The abstract methods in this class have a {@link Nullable} caster parameter (the caster is null when the
|
||||||
|
* spell is cast by a dispenser). When implementing this method, be sure to check whether the caster is {@code null}
|
||||||
|
* and deal with it appropriately.</i>
|
||||||
|
* <p></p>
|
||||||
|
* Properties added by this type of spell: {@link Spell#EFFECT_RADIUS}
|
||||||
|
* <p></p>
|
||||||
|
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastBy(EntityLiving, boolean)}
|
||||||
|
* <p></p>
|
||||||
|
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastBy(TileEntityDispenser)}
|
||||||
|
* <p></p>
|
||||||
|
* By default, this type of spell requires a packet to be sent. {@link Spell#requiresPacket()}
|
||||||
|
*
|
||||||
|
* @author Electroblob
|
||||||
|
* @since Wizardry 4.3
|
||||||
|
*/
|
||||||
public abstract class SpellAreaEffect extends Spell {
|
public abstract class SpellAreaEffect extends Spell {
|
||||||
|
|
||||||
// TODO: This class doesn't really work as it is right now, it needs rethinking. The aim is to try and have all the
|
/** True if this spell should target allies of the caster instead of hostiles. Positional casting always targets
|
||||||
// different casting methods call a single (abstract) positional method to do the actual AoE.
|
* everything, regardless of this setting. */
|
||||||
|
protected boolean targetAllies = false;
|
||||||
|
/** True if this spell should succeed even if no entities are affected, false if at least one entity must be affected. */
|
||||||
|
protected boolean alwaysSucceed = false;
|
||||||
/** The average number of particles to spawn per block in this spell's area of effect. */
|
/** The average number of particles to spawn per block in this spell's area of effect. */
|
||||||
protected float particleDensity = 0.65f;
|
protected float particleDensity = 0.65f;
|
||||||
|
|
||||||
public SpellAreaEffect(String name, EnumAction action){
|
public SpellAreaEffect(String name, EnumAction action, boolean continuous){
|
||||||
this(Wizardry.MODID, name, action);
|
this(Wizardry.MODID, name, action, continuous);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SpellAreaEffect(String modID, String name, EnumAction action){
|
public SpellAreaEffect(String modID, String name, EnumAction action, boolean continuous){
|
||||||
super(modID, name, action, false);
|
super(modID, name, action, continuous);
|
||||||
this.addProperties(EFFECT_RADIUS);
|
this.addProperties(EFFECT_RADIUS);
|
||||||
|
this.npcSelector((e, o) -> true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether this spell should target allies of the caster instead of hostiles. Positional casting always targets
|
||||||
|
* everything, regardless of this setting.
|
||||||
|
* @param targetAllies True to call {@link SpellAreaEffect#affectEntity(World, Vec3d, EntityLivingBase, EntityLivingBase, int, int, SpellModifiers)}
|
||||||
|
* on allies of the caster, false to call it on entities considered hostile to the caster (not
|
||||||
|
* necessarily <i>collectively-exhaustive</i>; some entities may belong to neither category).
|
||||||
|
* @return The spell instance, allowing this method to be chained onto the constructor.
|
||||||
|
*/
|
||||||
|
public SpellAreaEffect targetAllies(boolean targetAllies) {
|
||||||
|
this.targetAllies = targetAllies;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether this spell this spell should succeed even if no entities are affected.
|
||||||
|
* @param alwaysSucceed True if this spell should succeed even if no entities are affected, false if
|
||||||
|
* {@link SpellAreaEffect#affectEntity(World, Vec3d, EntityLivingBase, EntityLivingBase, int, int, SpellModifiers)}
|
||||||
|
* must return true at least once for the spell to succeed
|
||||||
|
* @return The spell instance, allowing this method to be chained onto the constructor.
|
||||||
|
*/
|
||||||
|
public SpellAreaEffect alwaysSucceed(boolean alwaysSucceed) {
|
||||||
|
this.alwaysSucceed = alwaysSucceed;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,57 +97,93 @@ public abstract class SpellAreaEffect extends Spell {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canBeCastBy(TileEntityDispenser dispenser){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
boolean result = findAndAffectEntities(world, new Vec3d(caster.posX, caster.getEntityBoundingBox().minY, caster.posZ),
|
||||||
|
caster, ticksInUse, modifiers);
|
||||||
|
if(result) this.playSound(world, caster, ticksInUse, -1, modifiers);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
List<EntityLivingBase> targets = EntityUtils.getEntitiesWithinRadius(getProperty(EFFECT_RADIUS).floatValue()
|
@Override
|
||||||
* modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world);
|
public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){
|
||||||
|
boolean result = findAndAffectEntities(world, caster.getPositionVector(), caster, ticksInUse, modifiers);
|
||||||
|
if(result) this.playSound(world, caster, ticksInUse, -1, modifiers);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
targets.removeIf(target -> !AllyDesignationSystem.isValidTarget(caster, target));
|
@Override
|
||||||
|
public boolean cast(World world, double x, double y, double z, EnumFacing direction, int ticksInUse, int duration, SpellModifiers modifiers){
|
||||||
|
boolean result = findAndAffectEntities(world, new Vec3d(x, y, z), null, ticksInUse, modifiers);
|
||||||
|
if(result) this.playSound(world, x, y, z, ticksInUse, -1, modifiers);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Takes care of the shared stuff for the three casting methods. This is mainly for internal use. */
|
||||||
|
protected boolean findAndAffectEntities(World world, Vec3d origin, @Nullable EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
|
||||||
|
double radius = getProperty(EFFECT_RADIUS).floatValue() * modifiers.get(WizardryItems.blast_upgrade);
|
||||||
|
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(radius, origin.x, origin.y, origin.z, world);
|
||||||
|
|
||||||
|
if(targetAllies){
|
||||||
|
targets.removeIf(target -> target != caster && !AllyDesignationSystem.isAllied(caster, target));
|
||||||
|
}else{
|
||||||
|
targets.removeIf(target -> !AllyDesignationSystem.isValidTarget(caster, target));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort by distance from the origin for consistency in ordering for spells with a limit
|
||||||
|
targets.sort(Comparator.comparingDouble(e -> e.getDistanceSq(origin.x, origin.y, origin.z)));
|
||||||
|
|
||||||
|
boolean result = alwaysSucceed;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
for(EntityLivingBase target : targets){
|
for(EntityLivingBase target : targets){
|
||||||
affectEntity(world, caster, target, modifiers);
|
if(affectEntity(world, origin, caster, target, i++, ticksInUse, modifiers)) result = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(world.isRemote){
|
if(world.isRemote) spawnParticleEffect(world, origin, radius, caster, modifiers);
|
||||||
spawnParticleEffect(world, caster, modifiers);
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
this.playSound(world, caster, ticksInUse, -1, modifiers);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to do something to each entity within the spell's area of effect.
|
* Called to do something to each entity within the spell's area of effect.
|
||||||
* @param world The world in which the spell was cast.
|
* @param world The world in which the spell was cast.
|
||||||
* @param caster The entity that cast the spell.
|
* @param origin The position the spell was cast from.
|
||||||
|
* @param caster The entity that cast the spell, or null if it was cast from a position.
|
||||||
* @param target The entity to do something to.
|
* @param target The entity to do something to.
|
||||||
|
* @param targetCount The number of targets that have already been affected, useful for spells with a target limit.
|
||||||
|
* Targets will be called in order of distance from the caster/origin,
|
||||||
|
* @param ticksInUse The number of ticks the spell has already been cast for.
|
||||||
* @param modifiers The modifiers the spell was cast with.
|
* @param modifiers The modifiers the spell was cast with.
|
||||||
|
* @return True if whatever was done to the entity was successful, false if not.
|
||||||
*/
|
*/
|
||||||
protected abstract void affectEntity(World world, EntityLivingBase caster, EntityLivingBase target, SpellModifiers modifiers);
|
protected abstract boolean affectEntity(World world, Vec3d origin, @Nullable EntityLivingBase caster, EntityLivingBase target, int targetCount, int ticksInUse, SpellModifiers modifiers);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to spawn the spell's particle effect. By default, this generates a set of random points within the spell's
|
* Called to spawn the spell's particle effect. By default, this generates a set of random points within the spell's
|
||||||
* area of effect and calls {@link SpellAreaEffect#spawnParticle(World, double, double, double)} at each to spawn
|
* area of effect and calls {@link SpellAreaEffect#spawnParticle(World, double, double, double)} at each to spawn
|
||||||
* the individual particles. Only called client-side. Override to add a custom particle effect.
|
* the individual particles. Only called client-side. Override to add a custom particle effect.
|
||||||
* @param world The world to spawn the particles in.
|
* @param world The world to spawn the particles in.
|
||||||
* @param caster The caster of the spell.
|
* @param origin The position the spell was cast from.
|
||||||
|
* @param radius The radius around the origin that was affected by this spell.
|
||||||
|
* @param caster The entity that cast the spell, or null if it was cast from a position.
|
||||||
* @param modifiers The modifiers the spell was cast with.
|
* @param modifiers The modifiers the spell was cast with.
|
||||||
*/
|
*/
|
||||||
protected void spawnParticleEffect(World world, EntityLivingBase caster, SpellModifiers modifiers){
|
protected void spawnParticleEffect(World world, Vec3d origin, double radius, @Nullable EntityLivingBase caster, SpellModifiers modifiers){
|
||||||
|
|
||||||
double maxRadius = getProperty(EFFECT_RADIUS).floatValue() * modifiers.get(WizardryItems.blast_upgrade);
|
int particleCount = (int)Math.round(particleDensity * Math.PI * radius * radius);
|
||||||
int particleCount = (int)Math.round(particleDensity * Math.PI * maxRadius * maxRadius);
|
|
||||||
|
|
||||||
for(int i=0; i<particleCount; i++){
|
for(int i=0; i<particleCount; i++){
|
||||||
|
|
||||||
double radius = (1 + world.rand.nextDouble() * (maxRadius - 1));
|
double r = (1 + world.rand.nextDouble() * (radius - 1));
|
||||||
float angle = world.rand.nextFloat() * (float)Math.PI * 2f;
|
float angle = world.rand.nextFloat() * (float)Math.PI * 2f;
|
||||||
|
|
||||||
spawnParticle(world, caster.posX + radius * MathHelper.cos(angle),
|
spawnParticle(world, origin.x + r * MathHelper.cos(angle), origin.y, origin.z + r * MathHelper.sin(angle));
|
||||||
caster.getEntityBoundingBox().minY,
|
|
||||||
caster.posZ + radius * MathHelper.sin(angle));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
"chargeup": 20,
|
"chargeup": 20,
|
||||||
"cooldown": 150,
|
"cooldown": 150,
|
||||||
"base_properties": {
|
"base_properties": {
|
||||||
"blast_radius": 5,
|
"effect_radius": 5,
|
||||||
"damage": 8,
|
"damage": 8,
|
||||||
"max_repulsion_velocity": 3
|
"max_repulsion_velocity": 3
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user