mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-17 10:24:23 +01:00
Further rewrites to the magic system
This commit is contained in:
parent
a58c6a0a44
commit
c5fdb9167f
24 changed files with 158 additions and 280 deletions
|
@ -10,14 +10,5 @@ public interface Attached extends Spell {
|
|||
* @param source The entity we are currently attached to.
|
||||
* @return true to keep alive
|
||||
*/
|
||||
boolean updateOnPerson(Caster<?> caster);
|
||||
|
||||
/**
|
||||
* Called every tick when attached to a living entity.
|
||||
* Used to apply particle effects.
|
||||
* Is only called on the client side.
|
||||
*
|
||||
* @param source The entity we are currently attached to.
|
||||
*/
|
||||
default void renderOnPerson(Caster<?> source) {}
|
||||
boolean onBodyTick(Caster<?> source);
|
||||
}
|
||||
|
|
|
@ -35,19 +35,6 @@ public interface Spell extends NbtSerialisable, Affine {
|
|||
*/
|
||||
void setDirty(boolean dirty);
|
||||
|
||||
/**
|
||||
* Gets the highest level this spell can be safely operated at.
|
||||
* Gems may go higher, however chance of explosion/exhaustion increases with every level.
|
||||
*/
|
||||
int getMaxLevelCutOff(Caster<?> caster);
|
||||
|
||||
float getMaxExhaustion(Caster<?> caster);
|
||||
|
||||
/**
|
||||
* Gets the chances of this effect turning into an innert gem or exploding.
|
||||
*/
|
||||
float getExhaustion(Caster<?> caster);
|
||||
|
||||
/**
|
||||
* Called when first attached to a gem.
|
||||
*/
|
||||
|
@ -66,29 +53,6 @@ public interface Spell extends NbtSerialisable, Affine {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every tick when attached to an entity.
|
||||
* Called on both sides.
|
||||
*
|
||||
* @param source The entity we are currently attached to.
|
||||
*/
|
||||
boolean update(Caster<?> source);
|
||||
|
||||
/**
|
||||
* Called every tick when attached to an entity to produce particle effects.
|
||||
* Is only called on the client side.
|
||||
*
|
||||
* @param source The entity we are attached to.
|
||||
*/
|
||||
void render(Caster<?> source);
|
||||
|
||||
/**
|
||||
* Return true to allow the gem update and move.
|
||||
*/
|
||||
default boolean allowAI() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new, deep-copied instance of this spell.
|
||||
*/
|
||||
|
|
|
@ -22,10 +22,18 @@ import net.minecraft.world.World;
|
|||
*/
|
||||
public interface Thrown extends Spell, ProjectileDelegate {
|
||||
|
||||
/**
|
||||
* Called every tick when attached to an entity.
|
||||
* Called on both sides.
|
||||
*
|
||||
* @param source The entity we are currently attached to.
|
||||
*/
|
||||
boolean onThrownTick(Caster<?> source);
|
||||
|
||||
@Override
|
||||
default void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {
|
||||
if (!projectile.isClient()) {
|
||||
update(projectile);
|
||||
onThrownTick(projectile);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
package com.minelittlepony.unicopia.ability.magic.spell;
|
||||
|
||||
import com.minelittlepony.unicopia.Affinity;
|
||||
import com.minelittlepony.unicopia.ability.magic.Attached;
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
|
||||
public abstract class AbstractRangedAreaSpell extends AbstractSpell implements Attached {
|
||||
|
||||
protected AbstractRangedAreaSpell(SpellType<?> type, Affinity affinity) {
|
||||
super(type, affinity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxLevelCutOff(Caster<?> source) {
|
||||
return 17;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMaxExhaustion(Caster<?> caster) {
|
||||
return 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getExhaustion(Caster<?> caster) {
|
||||
float max = getMaxLevelCutOff(caster);
|
||||
float current = caster.getLevel().get();
|
||||
|
||||
if (current > max) {
|
||||
float maxEc = getMaxExhaustion(caster);
|
||||
|
||||
current -= max;
|
||||
current /= max;
|
||||
current /= maxEc;
|
||||
|
||||
return maxEc - current;
|
||||
}
|
||||
|
||||
return super.getExhaustion(caster);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateOnPerson(Caster<?> caster) {
|
||||
return update(caster);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderOnPerson(Caster<?> caster) {
|
||||
render(caster);
|
||||
}
|
||||
}
|
|
@ -1,15 +1,14 @@
|
|||
package com.minelittlepony.unicopia.ability.magic.spell;
|
||||
|
||||
import com.minelittlepony.unicopia.Affinity;
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.Spell;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
||||
public abstract class AbstractSpell implements Spell {
|
||||
|
||||
protected boolean isDead;
|
||||
protected boolean isDirty;
|
||||
private boolean isDead;
|
||||
private boolean isDirty;
|
||||
|
||||
private final SpellType<?> type;
|
||||
|
||||
|
@ -45,21 +44,6 @@ public abstract class AbstractSpell implements Spell {
|
|||
isDirty = dirty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxLevelCutOff(Caster<?> source) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMaxExhaustion(Caster<?> caster) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getExhaustion(Caster<?> caster) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Affinity getAffinity() {
|
||||
return affinity;
|
||||
|
|
|
@ -31,7 +31,7 @@ public class AttractiveSpell extends ShieldSpell implements Thrown {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void render(Caster<?> source) {
|
||||
public void generateParticles(Caster<?> source) {
|
||||
int range = 4 + (source.getLevel().get() * 2);
|
||||
Vec3d pos = source.getOriginVector();
|
||||
|
||||
|
|
|
@ -23,27 +23,26 @@ public class AwkwardSpell extends AbstractSpell implements Thrown {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Caster<?> source) {
|
||||
public boolean onThrownTick(Caster<?> source) {
|
||||
if (source.isClient()) {
|
||||
source.spawnParticles(new Sphere(false, (1 + source.getLevel().get()) * 8), 10, pos -> {
|
||||
|
||||
List<Identifier> names = new ArrayList<>(Registry.PARTICLE_TYPE.getIds());
|
||||
|
||||
int index = (int)MathHelper.nextDouble(source.getWorld().random, 0, names.size());
|
||||
|
||||
Identifier id = names.get(index);
|
||||
ParticleType<?> type = Registry.PARTICLE_TYPE.get(id);
|
||||
|
||||
if (type instanceof ParticleEffect && shouldSpawnParticle(type)) {
|
||||
source.addParticle((ParticleEffect)type, pos, Vec3d.ZERO);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Caster<?> source) {
|
||||
source.spawnParticles(new Sphere(false, (1 + source.getLevel().get()) * 8), 10, pos -> {
|
||||
|
||||
List<Identifier> names = new ArrayList<>(Registry.PARTICLE_TYPE.getIds());
|
||||
|
||||
int index = (int)MathHelper.nextDouble(source.getWorld().random, 0, names.size());
|
||||
|
||||
Identifier id = names.get(index);
|
||||
ParticleType<?> type = Registry.PARTICLE_TYPE.get(id);
|
||||
|
||||
if (type instanceof ParticleEffect && shouldSpawnParticle(type)) {
|
||||
source.addParticle((ParticleEffect)type, pos, Vec3d.ZERO);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected boolean shouldSpawnParticle(ParticleType<?> type) {
|
||||
return type != ParticleTypes.BARRIER
|
||||
&& type != ParticleTypes.SMOKE
|
||||
|
|
|
@ -78,17 +78,21 @@ public class DisguiseSpell extends AbstractSpell implements Attached, Suppressab
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean updateOnPerson(Caster<?> caster) {
|
||||
return update(caster);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Caster<?> source) {
|
||||
public boolean onBodyTick(Caster<?> source) {
|
||||
return update(source, true);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean update(Caster<?> source, boolean tick) {
|
||||
if (source.isClient()) {
|
||||
if (isSuppressed()) {
|
||||
source.spawnParticles(MagicParticleEffect.UNICORN, 5);
|
||||
source.spawnParticles(UParticles.CHANGELING_MAGIC, 5);
|
||||
} else if (source.getWorld().random.nextInt(30) == 0) {
|
||||
source.spawnParticles(UParticles.CHANGELING_MAGIC, 2);
|
||||
}
|
||||
}
|
||||
|
||||
LivingEntity owner = source.getMaster();
|
||||
|
||||
Entity entity = disguise.getAppearance();
|
||||
|
@ -168,16 +172,6 @@ public class DisguiseSpell extends AbstractSpell implements Attached, Suppressab
|
|||
disguise.remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Caster<?> source) {
|
||||
if (isSuppressed()) {
|
||||
source.spawnParticles(MagicParticleEffect.UNICORN, 5);
|
||||
source.spawnParticles(UParticles.CHANGELING_MAGIC, 5);
|
||||
} else if (source.getWorld().random.nextInt(30) == 0) {
|
||||
source.spawnParticles(UParticles.CHANGELING_MAGIC, 2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toNBT(CompoundTag compound) {
|
||||
super.toNBT(compound);
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.ability.magic.spell;
|
|||
|
||||
import com.minelittlepony.unicopia.Affinity;
|
||||
import com.minelittlepony.unicopia.EquinePredicates;
|
||||
import com.minelittlepony.unicopia.ability.magic.Attached;
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.Magical;
|
||||
import com.minelittlepony.unicopia.ability.magic.Thrown;
|
||||
|
@ -35,7 +36,7 @@ import net.minecraft.world.explosion.Explosion.DestructionType;
|
|||
/**
|
||||
* Simple fire spell that triggers an effect when used on a block.
|
||||
*/
|
||||
public class FireSpell extends AbstractRangedAreaSpell implements Thrown {
|
||||
public class FireSpell extends AbstractSpell implements Thrown, Attached {
|
||||
|
||||
private static final Shape VISUAL_EFFECT_RANGE = new Sphere(false, 0.5);
|
||||
private static final Shape EFFECT_RANGE = new Sphere(false, 4);
|
||||
|
@ -52,15 +53,23 @@ public class FireSpell extends AbstractRangedAreaSpell implements Thrown {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Caster<?> source) {
|
||||
public boolean onBodyTick(Caster<?> source) {
|
||||
return onThrownTick(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onThrownTick(Caster<?> source) {
|
||||
if (source.isClient()) {
|
||||
generateParticles(source);
|
||||
}
|
||||
|
||||
return PosHelper.getAllInRegionMutable(source.getOrigin(), EFFECT_RANGE).reduce(false,
|
||||
(r, i) -> applyBlocks(source.getWorld(), i),
|
||||
(a, b) -> a || b)
|
||||
|| applyEntities(null, source.getWorld(), source.getOriginVector());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Caster<?> source) {
|
||||
protected void generateParticles(Caster<?> source) {
|
||||
source.spawnParticles(VISUAL_EFFECT_RANGE, source.getLevel().get() * 6, pos -> {
|
||||
source.addParticle(ParticleTypes.LARGE_SMOKE, pos, Vec3d.ZERO);
|
||||
});
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
package com.minelittlepony.unicopia.ability.magic.spell;
|
||||
|
||||
import com.minelittlepony.unicopia.Affinity;
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||
|
||||
public class GenericSpell extends AbstractSpell {
|
||||
|
||||
protected GenericSpell(SpellType<?> type, Affinity affinity) {
|
||||
super(type, affinity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Caster<?> source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Caster<?> source) {
|
||||
source.spawnParticles(new MagicParticleEffect(getType().getColor()), 1);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package com.minelittlepony.unicopia.ability.magic.spell;
|
||||
|
||||
import com.minelittlepony.unicopia.Affinity;
|
||||
import com.minelittlepony.unicopia.ability.magic.Attached;
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.Thrown;
|
||||
import com.minelittlepony.unicopia.block.state.StateMaps;
|
||||
|
@ -24,7 +25,7 @@ import net.minecraft.util.math.BlockPos;
|
|||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class IceSpell extends AbstractRangedAreaSpell implements Thrown {
|
||||
public class IceSpell extends AbstractSpell implements Thrown, Attached {
|
||||
|
||||
private final int rad = 3;
|
||||
private final Shape effect_range = new Sphere(false, rad);
|
||||
|
@ -34,7 +35,12 @@ public class IceSpell extends AbstractRangedAreaSpell implements Thrown {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Caster<?> source) {
|
||||
public boolean onBodyTick(Caster<?> source) {
|
||||
return onThrownTick(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onThrownTick(Caster<?> source) {
|
||||
LivingEntity owner = source.getMaster();
|
||||
|
||||
PosHelper.getAllInRegionMutable(source.getOrigin(), effect_range)
|
||||
|
@ -43,10 +49,6 @@ public class IceSpell extends AbstractRangedAreaSpell implements Thrown {
|
|||
return applyEntities(source.getMaster(), source.getWorld(), source.getOriginVector());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Caster<?> source) {
|
||||
}
|
||||
|
||||
protected boolean applyEntities(LivingEntity owner, World world, Vec3d pos) {
|
||||
return !VecHelper.findInRange(owner, world, pos, 3, i -> applyEntitySingle(owner, i)).isEmpty();
|
||||
}
|
||||
|
@ -85,13 +87,13 @@ public class IceSpell extends AbstractRangedAreaSpell implements Thrown {
|
|||
world.addParticle(ParticleTypes.SPLASH, pos.getX() + world.random.nextFloat(), pos.getY() + 1, pos.getZ() + world.random.nextFloat(), 0, 0, 0);
|
||||
}
|
||||
|
||||
public static boolean isSurroundedByIce(World w, BlockPos pos) {
|
||||
private static boolean isSurroundedByIce(World w, BlockPos pos) {
|
||||
return !PosHelper.adjacentNeighbours(pos).anyMatch(i ->
|
||||
w.getBlockState(i).getMaterial() == Material.ICE
|
||||
);
|
||||
}
|
||||
|
||||
private void incrementIce(World world, BlockPos pos) {
|
||||
private static void incrementIce(World world, BlockPos pos) {
|
||||
BlockState state = world.getBlockState(pos);
|
||||
Block id = state.getBlock();
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ public class InfernoSpell extends FireSpell {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Caster<?> source) {
|
||||
public boolean onThrownTick(Caster<?> source) {
|
||||
World w = source.getWorld();
|
||||
|
||||
if (!w.isClient) {
|
||||
|
|
|
@ -2,8 +2,8 @@ package com.minelittlepony.unicopia.ability.magic.spell;
|
|||
|
||||
import com.minelittlepony.unicopia.Affinity;
|
||||
import com.minelittlepony.unicopia.UTags;
|
||||
import com.minelittlepony.unicopia.ability.magic.Attached;
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.Thrown;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.particle.OrientedBillboardParticleEffect;
|
||||
import com.minelittlepony.unicopia.particle.ParticleHandle;
|
||||
|
@ -21,7 +21,7 @@ import net.minecraft.util.math.BlockPos;
|
|||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.GameRules;
|
||||
|
||||
public class JoustingSpell extends AbstractRangedAreaSpell implements Thrown {
|
||||
public class JoustingSpell extends AbstractSpell implements Attached {
|
||||
|
||||
private final int rad = 5;
|
||||
private final Shape effect_range = new Sphere(false, rad);
|
||||
|
@ -41,7 +41,14 @@ public class JoustingSpell extends AbstractRangedAreaSpell implements Thrown {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Caster<?> source) {
|
||||
public boolean onBodyTick(Caster<?> source) {
|
||||
if (source.isClient()) {
|
||||
particlEffect.ifAbsent(source, spawner -> {
|
||||
spawner.addParticle(UParticles.RAINBOOM_TRAIL, source.getOriginVector(), Vec3d.ZERO);
|
||||
spawner.addParticle(new OrientedBillboardParticleEffect(UParticles.RAINBOOM_RING, source.getPhysics().getMotionAngle()), source.getOriginVector(), Vec3d.ZERO);
|
||||
}).ifPresent(p -> p.attach(source));
|
||||
}
|
||||
|
||||
LivingEntity owner = source.getMaster();
|
||||
|
||||
source.findAllEntitiesInRange(rad).forEach(e -> {
|
||||
|
@ -78,14 +85,6 @@ public class JoustingSpell extends AbstractRangedAreaSpell implements Thrown {
|
|||
return entity.world.getGameRules().getBoolean(GameRules.DO_MOB_GRIEFING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Caster<?> source) {
|
||||
particlEffect.ifAbsent(source, spawner -> {
|
||||
spawner.addParticle(UParticles.RAINBOOM_TRAIL, source.getOriginVector(), Vec3d.ZERO);
|
||||
spawner.addParticle(new OrientedBillboardParticleEffect(UParticles.RAINBOOM_RING, source.getPhysics().getMotionAngle()), source.getOriginVector(), Vec3d.ZERO);
|
||||
}).ifPresent(p -> p.attach(source));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toNBT(CompoundTag compound) {
|
||||
super.toNBT(compound);
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.util.List;
|
|||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.minelittlepony.unicopia.Affinity;
|
||||
import com.minelittlepony.unicopia.ability.magic.Attached;
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.util.WorldEvent;
|
||||
import com.minelittlepony.unicopia.util.shape.Shape;
|
||||
|
@ -18,7 +19,7 @@ import net.minecraft.util.math.MathHelper;
|
|||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.Difficulty;
|
||||
|
||||
public class NecromancySpell extends AbstractRangedAreaSpell {
|
||||
public class NecromancySpell extends AbstractSpell implements Attached {
|
||||
|
||||
private final List<EntityType<? extends LivingEntity>> spawns = Lists.newArrayList(
|
||||
EntityType.ZOMBIE,
|
||||
|
@ -31,16 +32,28 @@ public class NecromancySpell extends AbstractRangedAreaSpell {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Caster<?> source) {
|
||||
public boolean onBodyTick(Caster<?> source) {
|
||||
|
||||
if (source.getWorld().isClient || source.getWorld().getDifficulty() == Difficulty.PEACEFUL) {
|
||||
int radius = source.getLevel().get() + 1;
|
||||
|
||||
if (source.isClient()) {
|
||||
Shape affectRegion = new Sphere(false, radius * 4);
|
||||
|
||||
source.spawnParticles(affectRegion, 5, pos -> {
|
||||
if (!source.getWorld().isAir(new BlockPos(pos).down())) {
|
||||
source.addParticle(ParticleTypes.FLAME, pos, Vec3d.ZERO);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (source.getWorld().getDifficulty() == Difficulty.PEACEFUL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
float additional = source.getWorld().getLocalDifficulty(source.getOrigin()).getLocalDifficulty();
|
||||
|
||||
int radius = source.getLevel().get() + 1;
|
||||
|
||||
Shape affectRegion = new Sphere(false, radius * 4);
|
||||
|
||||
if (source.getWorld().random.nextInt(100) != 0) {
|
||||
|
@ -80,15 +93,4 @@ public class NecromancySpell extends AbstractRangedAreaSpell {
|
|||
|
||||
source.getWorld().spawnEntity(zombie);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Caster<?> source) {
|
||||
Shape affectRegion = new Sphere(false, (1 + source.getLevel().get()) * 4);
|
||||
|
||||
source.spawnParticles(affectRegion, 5, pos -> {
|
||||
if (!source.getWorld().isAir(new BlockPos(pos).down())) {
|
||||
source.addParticle(ParticleTypes.FLAME, pos, Vec3d.ZERO);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.minelittlepony.unicopia.ability.magic.spell;
|
||||
|
||||
import com.minelittlepony.unicopia.Affinity;
|
||||
import com.minelittlepony.unicopia.ability.magic.Attached;
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.Suppressable;
|
||||
import com.minelittlepony.unicopia.ability.magic.Thrown;
|
||||
|
@ -15,7 +16,7 @@ import net.minecraft.util.math.Vec3d;
|
|||
/**
|
||||
* A spell for revealing changelings.
|
||||
*/
|
||||
public class RevealingSpell extends AbstractSpell implements Thrown {
|
||||
public class RevealingSpell extends AbstractSpell implements Attached, Thrown {
|
||||
private static final Shape AREA = new Sphere(false, 15);
|
||||
|
||||
protected RevealingSpell(SpellType<?> type, Affinity affinity) {
|
||||
|
@ -28,7 +29,22 @@ public class RevealingSpell extends AbstractSpell implements Thrown {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Caster<?> source) {
|
||||
public boolean onBodyTick(Caster<?> source) {
|
||||
return onThrownTick(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onThrownTick(Caster<?> source) {
|
||||
|
||||
if (source.isClient()) {
|
||||
MagicParticleEffect effect = new MagicParticleEffect(getType().getColor());
|
||||
|
||||
source.spawnParticles(AREA, 5, pos -> {
|
||||
source.addParticle(effect, pos, Vec3d.ZERO);
|
||||
});
|
||||
source.spawnParticles(effect, 5);
|
||||
}
|
||||
|
||||
source.findAllSpellsInRange(15).forEach(e -> {
|
||||
Suppressable spell = e.getSpell(Suppressable.class, false);
|
||||
|
||||
|
@ -40,14 +56,4 @@ public class RevealingSpell extends AbstractSpell implements Thrown {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Caster<?> source) {
|
||||
MagicParticleEffect effect = new MagicParticleEffect(getType().getColor());
|
||||
|
||||
source.spawnParticles(AREA, 5, pos -> {
|
||||
source.addParticle(effect, pos, Vec3d.ZERO);
|
||||
});
|
||||
source.spawnParticles(effect, 5);
|
||||
}
|
||||
}
|
|
@ -22,7 +22,7 @@ public class ScorchSpell extends FireSpell {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Caster<?> source) {
|
||||
public boolean onThrownTick(Caster<?> source) {
|
||||
|
||||
BlockPos pos = PosHelper.findSolidGroundAt(source.getWorld(), source.getOrigin(), source.getPhysics().getGravitySignum());
|
||||
|
||||
|
@ -41,7 +41,7 @@ public class ScorchSpell extends FireSpell {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void render(Caster<?> source) {
|
||||
protected void generateParticles(Caster<?> source) {
|
||||
source.addParticle(ParticleTypes.END_ROD, source.getOriginVector(), Vec3d.ZERO);
|
||||
source.spawnParticles(ParticleTypes.FLAME, 3);
|
||||
source.spawnParticles(new MagicParticleEffect(getType().getColor()), 3);
|
||||
|
|
|
@ -11,6 +11,7 @@ import com.minelittlepony.unicopia.EquinePredicates;
|
|||
import com.minelittlepony.unicopia.Unicopia;
|
||||
import com.minelittlepony.unicopia.ability.magic.Attached;
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.Thrown;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.item.FriendshipBraceletItem;
|
||||
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
||||
|
@ -33,7 +34,7 @@ import net.minecraft.entity.vehicle.BoatEntity;
|
|||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public class ShieldSpell extends AbstractRangedAreaSpell implements Attached {
|
||||
public class ShieldSpell extends AbstractSpell implements Attached, Thrown {
|
||||
|
||||
private final ParticleHandle particlEffect = new ParticleHandle();
|
||||
|
||||
|
@ -49,8 +50,7 @@ public class ShieldSpell extends AbstractRangedAreaSpell implements Attached {
|
|||
particlEffect.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Caster<?> source) {
|
||||
protected void generateParticles(Caster<?> source) {
|
||||
float radius = (float)getDrawDropOffRange(source);
|
||||
|
||||
source.spawnParticles(new Sphere(true, radius), (int)(radius * 6), pos -> {
|
||||
|
@ -67,7 +67,21 @@ public class ShieldSpell extends AbstractRangedAreaSpell implements Attached {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean updateOnPerson(Caster<?> source) {
|
||||
public boolean onThrownTick(Caster<?> source) {
|
||||
if (source.isClient()) {
|
||||
generateParticles(source);
|
||||
}
|
||||
|
||||
applyEntities(source);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBodyTick(Caster<?> source) {
|
||||
if (source.isClient()) {
|
||||
generateParticles(source);
|
||||
}
|
||||
|
||||
long costMultiplier = applyEntities(source);
|
||||
if (costMultiplier > 0) {
|
||||
double cost = 2 + source.getLevel().get();
|
||||
|
@ -91,12 +105,6 @@ public class ShieldSpell extends AbstractRangedAreaSpell implements Attached {
|
|||
return (4 + (source.getLevel().get() * 2)) / multiplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Caster<?> source) {
|
||||
applyEntities(source);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected List<Entity> getTargets(Caster<?> source, double radius) {
|
||||
|
||||
Entity owner = source.getMaster();
|
||||
|
|
|
@ -5,8 +5,8 @@ import java.util.stream.Collectors;
|
|||
|
||||
import com.minelittlepony.unicopia.Affinity;
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.ability.magic.Attached;
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.Thrown;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.util.MagicalDamageSource;
|
||||
import com.minelittlepony.unicopia.util.shape.Sphere;
|
||||
|
@ -21,17 +21,31 @@ import net.minecraft.util.math.Vec3d;
|
|||
/**
|
||||
* A spell that pulls health from other entities and delivers it to the caster.
|
||||
*/
|
||||
public class SiphoningSpell extends AbstractRangedAreaSpell implements Thrown {
|
||||
public class SiphoningSpell extends AbstractSpell implements Attached {
|
||||
|
||||
protected SiphoningSpell(SpellType<?> type, Affinity affinity) {
|
||||
super(type, affinity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Caster<?> source) {
|
||||
|
||||
public boolean onBodyTick(Caster<?> source) {
|
||||
int radius = 4 + source.getLevel().get();
|
||||
|
||||
if (source.isClient()) {
|
||||
Vec3d origin = source.getOriginVector();
|
||||
int direction = !isEnemy(source) ? 1 : -1;
|
||||
|
||||
source.spawnParticles(new Sphere(true, radius, 1, 0, 1), 1, pos -> {
|
||||
if (!source.getWorld().isAir(new BlockPos(pos).down())) {
|
||||
|
||||
double dist = pos.distanceTo(origin);
|
||||
Vec3d velocity = pos.subtract(origin).normalize().multiply(direction * dist);
|
||||
|
||||
source.addParticle(direction == 1 ? ParticleTypes.HEART : ParticleTypes.ANGRY_VILLAGER, pos, velocity);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
LivingEntity owner = source.getMaster();
|
||||
|
||||
List<LivingEntity> target = source.findAllEntitiesInRange(radius)
|
||||
|
@ -39,7 +53,7 @@ public class SiphoningSpell extends AbstractRangedAreaSpell implements Thrown {
|
|||
.map(e -> (LivingEntity)e)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
DamageSource damage = damageSource(owner);
|
||||
DamageSource damage = MagicalDamageSource.create("drain", owner);
|
||||
|
||||
if (!isFriendlyTogether(source)) {
|
||||
if (owner != null) {
|
||||
|
@ -94,30 +108,4 @@ public class SiphoningSpell extends AbstractRangedAreaSpell implements Thrown {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected DamageSource damageSource(LivingEntity actor) {
|
||||
if (actor == null) {
|
||||
return MagicalDamageSource.create("drain");
|
||||
}
|
||||
|
||||
return MagicalDamageSource.create("drain", actor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Caster<?> source) {
|
||||
int radius = 4 + source.getLevel().get();
|
||||
|
||||
Vec3d origin = source.getOriginVector();
|
||||
int direction = !isEnemy(source) ? 1 : -1;
|
||||
|
||||
source.spawnParticles(new Sphere(true, radius, 1, 0, 1), 1, pos -> {
|
||||
if (!source.getWorld().isAir(new BlockPos(pos).down())) {
|
||||
|
||||
double dist = pos.distanceTo(origin);
|
||||
Vec3d velocity = pos.subtract(origin).normalize().multiply(direction * dist);
|
||||
|
||||
source.addParticle(direction == 1 ? ParticleTypes.HEART : ParticleTypes.ANGRY_VILLAGER, pos, velocity);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.minelittlepony.unicopia.entity;
|
||||
|
||||
import com.minelittlepony.unicopia.ability.magic.Magical;
|
||||
import com.minelittlepony.unicopia.item.UItems;
|
||||
import com.minelittlepony.unicopia.network.Channel;
|
||||
import com.minelittlepony.unicopia.network.MsgSpawnProjectile;
|
||||
|
@ -19,7 +20,7 @@ import net.minecraft.util.math.MathHelper;
|
|||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class FloatingArtefactEntity extends Entity {
|
||||
public class FloatingArtefactEntity extends Entity implements Magical {
|
||||
|
||||
private static final TrackedData<ItemStack> ITEM = DataTracker.registerData(FloatingArtefactEntity.class, TrackedDataHandlerRegistry.ITEM_STACK);
|
||||
private static final TrackedData<Byte> STATE = DataTracker.registerData(FloatingArtefactEntity.class, TrackedDataHandlerRegistry.BYTE);
|
||||
|
|
|
@ -83,11 +83,7 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
|
|||
Attached effect = getSpell(Attached.class, true);
|
||||
|
||||
if (effect != null) {
|
||||
if (entity.getEntityWorld().isClient()) {
|
||||
effect.renderOnPerson(this);
|
||||
}
|
||||
|
||||
if (!effect.updateOnPerson(this)) {
|
||||
if (!effect.onBodyTick(this)) {
|
||||
setSpell(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.minelittlepony.unicopia.entity.behaviour;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.DisguiseSpell;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.util.Optional;
|
|||
|
||||
import com.minelittlepony.common.util.animation.MotionCompositor;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.DisguiseSpell;
|
||||
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public class PlayerCamera extends MotionCompositor {
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.minelittlepony.unicopia.ability.magic.Caster;
|
|||
import com.minelittlepony.unicopia.ability.magic.Levelled;
|
||||
import com.minelittlepony.unicopia.ability.magic.Magical;
|
||||
import com.minelittlepony.unicopia.ability.magic.Spell;
|
||||
import com.minelittlepony.unicopia.ability.magic.Thrown;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.SpellType;
|
||||
import com.minelittlepony.unicopia.entity.EntityPhysics;
|
||||
import com.minelittlepony.unicopia.entity.Physics;
|
||||
|
@ -162,16 +163,12 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Magical,
|
|||
lastBlockPos = getBlockPos();
|
||||
}
|
||||
|
||||
Spell spell = getSpell(true);
|
||||
Thrown spell = getSpell(Thrown.class, true);
|
||||
|
||||
if (spell.isDead()) {
|
||||
remove();
|
||||
} else {
|
||||
spell.update(this);
|
||||
|
||||
if (world.isClient()) {
|
||||
spell.render(this);
|
||||
}
|
||||
spell.onThrownTick(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ public class MagicalDamageSource extends EntityDamageSource {
|
|||
this(type, null, direct, unblockable);
|
||||
}
|
||||
|
||||
protected MagicalDamageSource(String type, Entity source, boolean direct, boolean unblockable) {
|
||||
protected MagicalDamageSource(String type, @Nullable Entity source, boolean direct, boolean unblockable) {
|
||||
super(type, source);
|
||||
setUsesMagic();
|
||||
if (direct) {
|
||||
|
|
Loading…
Reference in a new issue