diff --git a/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java index 40af8028..a60a1d9d 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java @@ -117,8 +117,8 @@ public class UnicornCastingAbility implements Ability { player.playSound(USounds.SPELL_CAST_FAIL, 1, 0.5F); } else { player.setAnimation(Animation.ARMS_UP); - if (s instanceof HomingSpell) { - RayTraceHelper.doTrace(player.getMaster(), 600, 1, EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.and(EntityPredicates.VALID_ENTITY)).getEntity().ifPresent(((HomingSpell)s)::setTarget); + if (s instanceof HomingSpell homer) { + RayTraceHelper.doTrace(player.getMaster(), homer.getRange(player), 1, EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.and(EntityPredicates.VALID_ENTITY)).getEntity().ifPresent(homer::setTarget); } player.playSound(USounds.SPELL_CAST_SUCCESS, 0.05F, 2.2F); } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/UnicornDispellAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/UnicornDispellAbility.java index f49dc43c..0880e713 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/UnicornDispellAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/UnicornDispellAbility.java @@ -76,7 +76,7 @@ public class UnicornDispellAbility implements Ability { @Override public void apply(Pony player, Pos data) { player.setAnimation(Animation.WOLOLO); - Caster.stream(VecHelper.findInRange(player.getEntity(), player.getReferenceWorld(), data.vec(), 2, EquinePredicates.IS_PLACED_SPELL).stream()).forEach(target -> { + Caster.stream(VecHelper.findInRange(player.getEntity(), player.getReferenceWorld(), data.vec(), 3, EquinePredicates.IS_PLACED_SPELL).stream()).forEach(target -> { target.getSpellSlot().clear(); }); } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/data/Pos.java b/src/main/java/com/minelittlepony/unicopia/ability/data/Pos.java index e1fc7037..15b082d8 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/data/Pos.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/data/Pos.java @@ -3,8 +3,7 @@ package com.minelittlepony.unicopia.ability.data; import com.minelittlepony.unicopia.ability.magic.Caster; import net.minecraft.network.PacketByteBuf; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.*; public class Pos extends Hit { @@ -44,7 +43,7 @@ public class Pos extends Hit { } public Vec3d vec() { - return new Vec3d(x, y, z); + return Vec3d.ofCenter(new Vec3i(x, y, z)); } public double distanceTo(Caster caster) { diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/HomingSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/HomingSpell.java index 2e7908fa..e951bea1 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/HomingSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/HomingSpell.java @@ -1,10 +1,18 @@ package com.minelittlepony.unicopia.ability.magic.spell; +import com.minelittlepony.unicopia.ability.magic.Caster; + import net.minecraft.entity.Entity; /** * A spell that's capable of homing in on a pre-defined target. */ public interface HomingSpell extends Spell { + int DEFAULT_RANGE = 600; + boolean setTarget(Entity target); + + default int getRange(Caster caster) { + return DEFAULT_RANGE; + } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java index bff00f5f..cefa0cb6 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java @@ -50,6 +50,9 @@ public class PlaceableSpell extends AbstractDelegatingSpell { */ private Spell spell; + public float pitch; + public float yaw; + public PlaceableSpell(CustomisedSpellType type) { super(type); } @@ -84,7 +87,11 @@ public class PlaceableSpell extends AbstractDelegatingSpell { CastSpellEntity entity = UEntities.CAST_SPELL.create(source.getReferenceWorld()); Vec3d pos = castEntity.getPosition().orElse(source.getOriginVector()); entity.updatePositionAndAngles(pos.x, pos.y, pos.z, 0, 0); - entity.getSpellSlot().put(spell.toPlaceable()); + PlaceableSpell copy = spell.toPlaceable(); + if (spell instanceof PlacementDelegate delegate) { + delegate.onPlaced(source, copy, entity); + } + entity.getSpellSlot().put(copy); entity.setMaster(source); entity.world.spawnEntity(entity); Ether.get(entity.world).put(getType(), entity); @@ -113,9 +120,11 @@ public class PlaceableSpell extends AbstractDelegatingSpell { } } - particlEffect.update(getUuid(), source, spawner -> { - spawner.addParticle(new OrientedBillboardParticleEffect(UParticles.MAGIC_RUNES, 90, 0), source.getOriginVector(), Vec3d.ZERO); - }).ifPresent(p -> { + if (spell instanceof PlacementDelegate delegate) { + delegate.updatePlacement(source, this); + } + + getParticleEffectAttachment(source).ifPresent(p -> { p.setAttribute(Attachment.ATTR_COLOR, spell.getType().getColor()); }); @@ -145,6 +154,13 @@ public class PlaceableSpell extends AbstractDelegatingSpell { return getWorld(source).map(castEntity::get); } + public Optional getParticleEffectAttachment(Caster source) { + return particlEffect.update(getUuid(), source, spawner -> { + source.getOriginVector().add(0, 5, 0); + spawner.addParticle(new OrientedBillboardParticleEffect(UParticles.MAGIC_RUNES, pitch + 90, yaw), Vec3d.ZERO, Vec3d.ZERO); + }); + } + protected Optional getWorld(Caster source) { return Optional.ofNullable(dimension) .map(dim -> source.getReferenceWorld().getServer().getWorld(dim)); @@ -153,6 +169,8 @@ public class PlaceableSpell extends AbstractDelegatingSpell { @Override public void toNBT(NbtCompound compound) { super.toNBT(compound); + compound.putFloat("pitch", pitch); + compound.putFloat("yaw", yaw); if (dimension != null) { compound.putString("dimension", dimension.getValue().toString()); } @@ -163,6 +181,8 @@ public class PlaceableSpell extends AbstractDelegatingSpell { @Override public void fromNBT(NbtCompound compound) { super.fromNBT(compound); + pitch = compound.getFloat("pitch"); + yaw = compound.getFloat("yaw"); if (compound.contains("dimension", NbtElement.STRING_TYPE)) { Identifier id = Identifier.tryParse(compound.getString("dimension")); if (id != null) { @@ -182,10 +202,18 @@ public class PlaceableSpell extends AbstractDelegatingSpell { @Override protected void saveDelegates(NbtCompound compound) { compound.put("spell", Spell.SERIALIZER.write(spell)); + } @Override public PlaceableSpell toPlaceable() { return this; } + + public interface PlacementDelegate { + + void onPlaced(Caster source, PlaceableSpell parent, CastSpellEntity entity); + + void updatePlacement(Caster source, PlaceableSpell parent); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java new file mode 100644 index 00000000..8c028d04 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java @@ -0,0 +1,112 @@ +package com.minelittlepony.unicopia.ability.magic.spell.effect; + +import com.minelittlepony.unicopia.ability.magic.Caster; +import com.minelittlepony.unicopia.ability.magic.spell.*; +import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; +import com.minelittlepony.unicopia.entity.CastSpellEntity; +import com.minelittlepony.unicopia.entity.EntityReference; +import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment; +import com.minelittlepony.unicopia.util.MagicalDamageSource; + +import net.minecraft.entity.Entity; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.sound.SoundEvents; +import net.minecraft.util.math.Vec3d; + +public class DisplacementSpell extends AbstractSpell implements HomingSpell, PlaceableSpell.PlacementDelegate { + + private final EntityReference target = new EntityReference<>(); + + private int ticks = 10; + + protected DisplacementSpell(CustomisedSpellType type) { + super(type); + } + + @Override + public boolean apply(Caster caster) { + return toPlaceable().apply(caster); + } + + @Override + public boolean tick(Caster source, Situation situation) { + source.getMaster().setGlowing(true); + + ticks--; + + if (source.isClient()) { + return !isDead() || ticks >= -10; + } + + if (ticks == 0) { + target.ifPresent(source.getReferenceWorld(), target -> { + + Vec3d destinationPos = target.getPos(); + Vec3d destinationVel = target.getVelocity(); + + Vec3d sourcePos = source.getMaster().getPos(); + Vec3d sourceVel = source.getMaster().getVelocity(); + + teleport(target, sourcePos, sourceVel); + teleport(source.getMaster(), destinationPos, destinationVel); + source.subtractEnergyCost(destinationPos.distanceTo(sourcePos) / 20F); + }); + } + + return ticks >= -10; + } + + @Override + public void onPlaced(Caster source, PlaceableSpell parent, CastSpellEntity entity) { + + } + + @Override + public void updatePlacement(Caster caster, PlaceableSpell parent) { + parent.getParticleEffectAttachment(caster).ifPresent(attachment -> { + float r = 3 - (1 - ((ticks + 10) / 20F)) * 3; + attachment.setAttribute(Attachment.ATTR_RADIUS, r); + }); + } + + private void teleport(Entity entity, Vec3d pos, Vec3d vel) { + entity.teleport(pos.x, pos.y, pos.z); + entity.setVelocity(vel); + entity.setGlowing(false); + entity.playSound(SoundEvents.ENTITY_HUSK_CONVERTED_TO_ZOMBIE, 1, 1); + + float damage = getTraits().get(Trait.BLOOD); + if (damage > 0) { + entity.damage(MagicalDamageSource.EXHAUSTION, damage); + } + } + + @Override + public boolean setTarget(Entity target) { + this.target.set(target); + return false; + } + + @Override + public int getRange(Caster caster) { + return 200 + Math.min(2000, 50 * (1 + caster.getLevel().get())); + } + + @Override + public void onDestroyed(Caster caster) { + caster.getMaster().setGlowing(false); + target.ifPresent(caster.getReferenceWorld(), e -> e.setGlowing(false)); + } + + @Override + public void toNBT(NbtCompound compound) { + super.toNBT(compound); + compound.putInt("ticks", ticks); + } + + @Override + public void fromNBT(NbtCompound compound) { + super.fromNBT(compound); + ticks = compound.getInt("ticks"); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java index 07f64e69..40edd90b 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java @@ -1,32 +1,46 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; +import java.util.Optional; + import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.ability.magic.Caster; -import com.minelittlepony.unicopia.ability.magic.spell.Situation; +import com.minelittlepony.unicopia.ability.magic.spell.*; +import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; +import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.block.data.Ether; import com.minelittlepony.unicopia.entity.CastSpellEntity; import com.minelittlepony.unicopia.entity.EntityReference; import com.minelittlepony.unicopia.particle.*; +import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment; import com.minelittlepony.unicopia.util.shape.Sphere; import net.minecraft.block.Block; import net.minecraft.block.Blocks; +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; import net.minecraft.nbt.NbtCompound; import net.minecraft.particle.ParticleEffect; import net.minecraft.particle.ParticleTypes; +import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.world.WorldEvents; -public class PortalSpell extends AbstractSpell { - public static final int MAX_COOLDOWN = 20; - private final EntityReference teleportationTarget = new EntityReference<>(); +public class PortalSpell extends AbstractSpell implements PlaceableSpell.PlacementDelegate { + public static final SpellTraits DEFAULT_TRAITS = new SpellTraits.Builder() + .with(Trait.LIFE, 10) + .with(Trait.KNOWLEDGE, 1) + .with(Trait.ORDER, 25) + .build(); + + private final EntityReference teleportationTarget = new EntityReference<>(); private boolean publishedPosition; - private final ParticleHandle particlEffect = new ParticleHandle(); + private final ParticleHandle particleEffect = new ParticleHandle(); - private int cooldown = MAX_COOLDOWN; + private float pitch; + private float yaw; protected PortalSpell(CustomisedSpellType type) { super(type); @@ -34,36 +48,17 @@ public class PortalSpell extends AbstractSpell { @Override public boolean apply(Caster caster) { + pitch = caster.getEntity().getPitch(1); + yaw = caster.getEntity().getYaw(1); return toPlaceable().apply(caster); } @Override public boolean tick(Caster source, Situation situation) { - if (situation == Situation.GROUND) { - if (!source.isClient()) { - teleportationTarget.getId().ifPresent(id -> { - Ether ether = Ether.get(source.getReferenceWorld()); - if (ether.getEntry(getType(), id).isEmpty()) { - Unicopia.LOGGER.debug("Lost sibling, breaking connection to " + id); - teleportationTarget.set(null); - setDirty(); - source.getReferenceWorld().syncWorldEvent(WorldEvents.BLOCK_BROKEN, source.getOrigin(), Block.getRawIdFromState(Blocks.GLASS.getDefaultState())); - } - }); - } - teleportationTarget.getPosition().ifPresentOrElse( - targetPos -> tickWithTargetLink(source, targetPos), - () -> findLink(source) - ); + if (source.isClient()) { - if (!publishedPosition) { - publishedPosition = true; - Ether.get(source.getReferenceWorld()).put(getType(), source); - } - - if (source.isClient() && cooldown <= 0) { Vec3d origin = source.getOriginVector(); ParticleEffect effect = teleportationTarget.getPosition() @@ -71,51 +66,78 @@ public class PortalSpell extends AbstractSpell { getType(); return new FollowingParticleEffect(UParticles.HEALTH_DRAIN, target, 0.2F).withChild(ParticleTypes.ELECTRIC_SPARK); }) - .orElseGet(() -> { - new MagicParticleEffect(getType().getColor()); - return ParticleTypes.ELECTRIC_SPARK; - }); + .orElse(ParticleTypes.ELECTRIC_SPARK); - source.spawnParticles(origin, new Sphere(true, 2, 1, 0, 1), 3, pos -> { + source.spawnParticles(origin, new Sphere(true, 2, 1, 1, 1), 1, pos -> { source.addParticle(effect, pos, Vec3d.ZERO); }); + + teleportationTarget.getPosition().ifPresentOrElse(position -> { + particleEffect.update(getUuid(), source, spawner -> { + spawner.addParticle(new SphereParticleEffect(UParticles.DISK, getType().getColor(), 0.8F, 2, new Vec3d(pitch, yaw, 0)), source.getOriginVector(), Vec3d.ZERO); + }); + }, () -> { + particleEffect.destroy(); + }); + } else { + teleportationTarget.getId().ifPresent(id -> { + if (Ether.get(source.getReferenceWorld()).getEntry(getType(), id).isEmpty()) { + Unicopia.LOGGER.debug("Lost sibling, breaking connection to " + id); + teleportationTarget.set(null); + setDirty(); + source.getReferenceWorld().syncWorldEvent(WorldEvents.BLOCK_BROKEN, source.getOrigin(), Block.getRawIdFromState(Blocks.GLASS.getDefaultState())); + } + }); + + getTarget(source).ifPresentOrElse( + entry -> tickWithTargetLink(source, entry), + () -> findLink(source) + ); } + + if (!publishedPosition) { + publishedPosition = true; + Ether.Entry entry = Ether.get(source.getReferenceWorld()).put(getType(), source); + entry.pitch = pitch; + entry.yaw = yaw; + } + + } - return true; + return !isDead(); } - private void tickWithTargetLink(Caster source, Vec3d targetPos) { - particlEffect.update(getUuid(), source, spawner -> { - spawner.addParticle(new SphereParticleEffect(UParticles.DISK, getType().getColor(), 0.8F, 2), source.getOriginVector(), Vec3d.ZERO); - }); + private void tickWithTargetLink(Caster source, Ether.Entry destination) { - if (cooldown > 0) { - cooldown--; - setDirty(); - return; - } + destination.entity.getPosition().ifPresent(targetPos -> { + Vec3d center = source.getOriginVector(); + source.findAllEntitiesInRange(1).filter(e -> true).forEach(entity -> { + if (!entity.hasPortalCooldown() && entity.timeUntilRegen <= 0) { + Vec3d offset = entity.getPos().subtract(center); + Vec3d dest = targetPos; + float yawDifference = pitch < 15 ? (180 - yaw + destination.yaw) : 0; - Vec3d center = source.getOriginVector(); - source.findAllEntitiesInRange(1).filter(e -> true).forEach(entity -> { - if (!entity.hasPortalCooldown() && entity.timeUntilRegen <= 0) { - Vec3d destination = entity.getPos().subtract(center).add(targetPos); - entity.resetPortalCooldown(); - entity.timeUntilRegen = 100; + dest = dest.add(offset.rotateY(yawDifference * MathHelper.RADIANS_PER_DEGREE)).add(0, 0.05, 0); - entity.playSound(USounds.ENTITY_PLAYER_UNICORN_TELEPORT, 1, 1); - entity.teleport(destination.x, destination.y, destination.z); - entity.playSound(USounds.ENTITY_PLAYER_UNICORN_TELEPORT, 1, 1); - setDirty(); - } + entity.resetPortalCooldown(); + entity.timeUntilRegen = 20; - ParticleUtils.spawnParticles(new MagicParticleEffect(getType().getColor()), entity, 7); + entity.setYaw(entity.getYaw() + yawDifference); + entity.setVelocity(entity.getVelocity().rotateY(yawDifference * MathHelper.RADIANS_PER_DEGREE)); + + entity.world.playSoundFromEntity(null, entity, USounds.ENTITY_PLAYER_UNICORN_TELEPORT, entity.getSoundCategory(), 1, 1); + entity.teleport(dest.x, dest.y, dest.z); + entity.world.playSoundFromEntity(null, entity, USounds.ENTITY_PLAYER_UNICORN_TELEPORT, entity.getSoundCategory(), 1, 1); + setDirty(); + } + + ParticleUtils.spawnParticles(new MagicParticleEffect(getType().getColor()), entity, 7); + }); }); } - @SuppressWarnings("unchecked") private void findLink(Caster source) { - if (source.isClient()) { return; } @@ -123,20 +145,50 @@ public class PortalSpell extends AbstractSpell { Ether ether = Ether.get(source.getReferenceWorld()); ether.getEntries(getType()) .stream() - .filter(entry -> entry.isAvailable() && !entry.entity.referenceEquals(source.getEntity())) + .filter(entry -> entry.isAvailable() && !entry.entity.referenceEquals(source.getEntity()) && entry.entity.getId().isPresent()) .findAny() .ifPresent(entry -> { entry.setTaken(true); - teleportationTarget.copyFrom((EntityReference)entry.entity); + teleportationTarget.copyFrom(entry.entity); setDirty(); }); } + private Optional getTarget(Caster source) { + return teleportationTarget.getId().flatMap(id -> Ether.get(source.getReferenceWorld()).getEntry(getType(), id)); + } + + @Override + public void onPlaced(Caster source, PlaceableSpell parent, CastSpellEntity entity) { + LivingEntity caster = source.getMaster(); + Vec3d targetPos = caster.getRotationVector().multiply(3).add(caster.getEyePos()); + + parent.pitch = -90 - pitch; + parent.yaw = -yaw; + + for (Spell delegate : parent.getDelegates()) { + if (delegate instanceof PortalSpell copy) { + copy.pitch = pitch; + copy.yaw = yaw; + } + } + + entity.setPos(targetPos.x, caster.getY() + 1.5, targetPos.z); + } + + @Override + public void updatePlacement(Caster source, PlaceableSpell parent) { + parent.getParticleEffectAttachment(source).ifPresent(attachment -> { + attachment.setAttribute(Attachment.ATTR_RADIUS, 2); + attachment.setAttribute(Attachment.ATTR_OPACITY, 0.92F); + }); + } + @Override public void onDestroyed(Caster caster) { Ether ether = Ether.get(caster.getReferenceWorld()); ether.remove(getType(), caster.getEntity().getUuid()); - teleportationTarget.getId().flatMap(id -> ether.getEntry(getType(), id)).ifPresent(e -> e.setTaken(false)); + getTarget(caster).ifPresent(e -> e.setTaken(false)); } @Override @@ -144,7 +196,8 @@ public class PortalSpell extends AbstractSpell { super.toNBT(compound); compound.putBoolean("publishedPosition", publishedPosition); compound.put("teleportationTarget", teleportationTarget.toNBT()); - compound.putInt("cooldown", cooldown); + compound.putFloat("pitch", pitch); + compound.putFloat("yaw", yaw); } @Override @@ -152,12 +205,13 @@ public class PortalSpell extends AbstractSpell { super.fromNBT(compound); publishedPosition = compound.getBoolean("publishedPosition"); teleportationTarget.fromNBT(compound.getCompound("teleportationTarget")); - cooldown = compound.getInt("cooldown"); + pitch = compound.getFloat("pitch"); + yaw = compound.getFloat("yaw"); } @Override public void setDead() { super.setDead(); - particlEffect.destroy(); + particleEffect.destroy(); } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SpellType.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SpellType.java index f16ed35a..5c87fa24 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SpellType.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SpellType.java @@ -60,7 +60,8 @@ public final class SpellType implements Affine, SpellPredicate< public static final SpellType CATAPULT = register("catapult", Affinity.GOOD, 0x22FF00, true, CatapultSpell.DEFAULT_TRAITS, CatapultSpell::new); public static final SpellType FIRE_BOLT = register("fire_bolt", Affinity.GOOD, 0xFF8811, true, FireBoltSpell.DEFAULT_TRAITS, FireBoltSpell::new); public static final SpellType LIGHT = register("light", Affinity.GOOD, 0xEEFFAA, true, LightSpell.DEFAULT_TRAITS, LightSpell::new); - public static final SpellType PORTAL = register("portal", Affinity.GOOD, 0x99FFFF, true, LightSpell.DEFAULT_TRAITS, PortalSpell::new); + public static final SpellType DISPLACEMENT = register("displacement", Affinity.NEUTRAL, 0x9900FF, true, PortalSpell.DEFAULT_TRAITS, DisplacementSpell::new); + public static final SpellType PORTAL = register("portal", Affinity.GOOD, 0x99FFFF, true, PortalSpell.DEFAULT_TRAITS, PortalSpell::new); public static void bootstrap() {} diff --git a/src/main/java/com/minelittlepony/unicopia/block/data/Ether.java b/src/main/java/com/minelittlepony/unicopia/block/data/Ether.java index aede3520..31bb45e1 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/data/Ether.java +++ b/src/main/java/com/minelittlepony/unicopia/block/data/Ether.java @@ -61,11 +61,12 @@ public class Ether extends PersistentState { } } - public void put(SpellType spellType, Caster caster) { + public Entry put(SpellType spellType, Caster caster) { synchronized (locker) { getEntries(spellType.getId()).add(new Entry(caster)); + markDirty(); + return getEntry(spellType, caster).get(); } - markDirty(); } public void remove(SpellType spellType, UUID id) { @@ -120,6 +121,9 @@ public class Ether extends PersistentState { private boolean removed; private boolean taken; + public float pitch; + public float yaw; + public Entry() { entity = new EntityReference<>(); } @@ -156,6 +160,8 @@ public class Ether extends PersistentState { entity.toNBT(compound); compound.putBoolean("removed", removed); compound.putBoolean("taken", taken); + compound.putFloat("pitch", pitch); + compound.putFloat("yaw", yaw); } @Override @@ -163,6 +169,8 @@ public class Ether extends PersistentState { entity.fromNBT(compound); removed = compound.getBoolean("removed"); taken = compound.getBoolean("taken"); + pitch = compound.getFloat("pitch"); + yaw = compound.getFloat("yaw"); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/DiskParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/DiskParticle.java index 2a2b6783..c3420fe1 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/particle/DiskParticle.java +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/DiskParticle.java @@ -5,15 +5,19 @@ import com.minelittlepony.unicopia.particle.SphereParticleEffect; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.world.ClientWorld; -import net.minecraft.util.math.Quaternion; +import net.minecraft.util.math.*; public class DiskParticle extends SphereParticle { - private final Quaternion rotation; + private final Quaternion rotation = new Quaternion(0, 0, 0, 1); public DiskParticle(SphereParticleEffect effect, ClientWorld w, double x, double y, double z, double rX, double rY, double rZ) { super(effect, w, x, y, z, 0, 0, 0); - rotation = new Quaternion((float)effect.getOffset().x, (float)effect.getOffset().y, (float)effect.getOffset().z, true); + + rotation.hamiltonProduct(Vec3f.POSITIVE_Y.getDegreesQuaternion((float)effect.getOffset().y)); + rotation.hamiltonProduct(Vec3f.POSITIVE_X.getDegreesQuaternion(90 - (float)effect.getOffset().x)); + + effect.setOffset(Vec3d.ZERO); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/OrientedBillboardParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/OrientedBillboardParticle.java index ebe972ce..3d083896 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/particle/OrientedBillboardParticle.java +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/OrientedBillboardParticle.java @@ -20,8 +20,8 @@ public abstract class OrientedBillboardParticle extends AbstractBillboardParticl fixed = effect.isAngleFixed(); if (fixed) { - rotation.hamiltonProduct(Vec3f.POSITIVE_X.getDegreesQuaternion(180 - effect.getYaw())); rotation.hamiltonProduct(Vec3f.POSITIVE_Y.getDegreesQuaternion(effect.getPitch())); + rotation.hamiltonProduct(Vec3f.POSITIVE_X.getDegreesQuaternion(180 - effect.getYaw())); } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/RainbowTrailParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/RainbowTrailParticle.java index 2075110b..ea3c37af 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/particle/RainbowTrailParticle.java +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/RainbowTrailParticle.java @@ -53,7 +53,7 @@ public class RainbowTrailParticle extends AbstractBillboardParticle implements A } @Override - public void setAttribute(int key, Object value) { + public void setAttribute(int key, Number value) { } diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/RunesParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/RunesParticle.java index c63698d9..5eaf31b7 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/particle/RunesParticle.java +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/RunesParticle.java @@ -30,6 +30,8 @@ public class RunesParticle extends OrientedBillboardParticle implements Attachme Unicopia.id("textures/particles/runes_5.png") }; + protected float targetSize = 3; + protected float prevBaseSize = 0; protected float baseSize = 0; @@ -61,22 +63,31 @@ public class RunesParticle extends OrientedBillboardParticle implements Attachme velocityY = 0; velocityZ = 0; Vec3d pos = link.get().map(Caster::getOriginVector).orElse(Vec3d.ZERO); - setPos(pos.x, pos.y, pos.z); + setPos(pos.x, pos.y + 0.25, pos.z); } @Override public void detach() { link = Optional.empty(); + if (targetSize > 1) { + this.targetSize = 0; + } } @Override - public void setAttribute(int key, Object value) { + public void setAttribute(int key, Number value) { if (key == ATTR_COLOR) { - int tint = (int)value; + int tint = value.intValue(); red = Color.r(tint); green = Color.g(tint); blue = Color.b(tint); } + if (key == ATTR_OPACITY) { + alpha = value.floatValue(); + } + if (key == ATTR_RADIUS) { + targetSize = value.floatValue(); + } } @Override public float getScale(float tickDelta) { @@ -137,6 +148,8 @@ public class RunesParticle extends OrientedBillboardParticle implements Attachme renderQuad(te, buffer, corners, alpha, tickDelta); } } + + RenderSystem.setShaderColor(1, 1, 1, 1); } @Override @@ -153,8 +166,11 @@ public class RunesParticle extends OrientedBillboardParticle implements Attachme }, this::detach); prevBaseSize = baseSize; - if (baseSize < 3) { - baseSize++; + if (baseSize < targetSize) { + baseSize += 0.1F; + } + if (baseSize > targetSize) { + baseSize -= 0.1F; } rotationAngle = (rotationAngle + 0.3F) % 360; diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/SphereParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/SphereParticle.java index 5a03b339..0b28f866 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/particle/SphereParticle.java +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/SphereParticle.java @@ -74,20 +74,20 @@ public class SphereParticle extends Particle implements Attachment { } @Override - public void setAttribute(int key, Object value) { + public void setAttribute(int key, Number value) { if (key == ATTR_RADIUS) { - toRadius = (float)value; + toRadius = value.floatValue(); steps = 20; lerpIncrement = (toRadius - radius) / steps; } if (key == ATTR_COLOR) { - int tint = (int)value; + int tint = value.intValue(); red = Color.r(tint); green = Color.g(tint); blue = Color.b(tint); } if (key == ATTR_OPACITY) { - alpha = (float)value; + alpha = value.floatValue(); } } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/EntityReference.java b/src/main/java/com/minelittlepony/unicopia/entity/EntityReference.java index 69697472..1332aa97 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/EntityReference.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/EntityReference.java @@ -33,7 +33,7 @@ public class EntityReference implements NbtSerialisable { fromNBT(nbt); } - public void copyFrom(EntityReference other) { + public void copyFrom(EntityReference other) { uuid = other.uuid; clientId = other.clientId; pos = other.pos; diff --git a/src/main/java/com/minelittlepony/unicopia/particle/ParticleHandle.java b/src/main/java/com/minelittlepony/unicopia/particle/ParticleHandle.java index 9ba5b778..fd32b560 100644 --- a/src/main/java/com/minelittlepony/unicopia/particle/ParticleHandle.java +++ b/src/main/java/com/minelittlepony/unicopia/particle/ParticleHandle.java @@ -95,7 +95,7 @@ public class ParticleHandle { void detach(); - void setAttribute(int key, Object value); + void setAttribute(int key, Number value); } public static final class Link { diff --git a/src/main/java/com/minelittlepony/unicopia/particle/SphereParticleEffect.java b/src/main/java/com/minelittlepony/unicopia/particle/SphereParticleEffect.java index 2446adf0..93b11c3f 100644 --- a/src/main/java/com/minelittlepony/unicopia/particle/SphereParticleEffect.java +++ b/src/main/java/com/minelittlepony/unicopia/particle/SphereParticleEffect.java @@ -60,6 +60,10 @@ public class SphereParticleEffect implements ParticleEffect { return offset; } + public void setOffset(Vec3d offset) { + this.offset = offset; + } + public Vec3f getColor() { return color; } diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index 15e20acc..1fe194b0 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -152,7 +152,9 @@ "spell.unicopia.vortex.lore": "Creates a magnetic force that pulls in other targets", "spell.unicopia.dark_vortex": "Dark Vortex", "spell.unicopia.dark_vortex.lore": "Creates a black hole from which nothing can escape", - "spell.unicopia.portal": "Teleportation", + "spell.unicopia.displacement": "Displacement", + "spell.unicopia.displacement.lore": "Swaps the caster's locatin with that of another entity", + "spell.unicopia.portal": "Arcane Rift", "spell.unicopia.portal.lore": "Connects two points in space for fast travel between", "spell.unicopia.necromancy": "Necromancy", "spell.unicopia.necromancy.lore": "Summons undead minions from beyond the grave",