From c0eeb5b5e1d018ec0d5110ae228f2c35998063f4 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 22 Nov 2021 00:48:40 +0200 Subject: [PATCH] Added the catapult spell type --- .../magic/spell/effect/CatapultSpell.java | 101 ++++++++++++++++++ .../magic/spell/effect/InfernoSpell.java | 3 + .../ability/magic/spell/effect/SpellType.java | 3 +- .../magic/spell/trait/SpellTraits.java | 11 +- 4 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CatapultSpell.java diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CatapultSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CatapultSpell.java new file mode 100644 index 00000000..a3f85b2c --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CatapultSpell.java @@ -0,0 +1,101 @@ +package com.minelittlepony.unicopia.ability.magic.spell.effect; + +import java.util.Optional; +import java.util.function.Consumer; + +import com.minelittlepony.unicopia.ability.magic.Caster; +import com.minelittlepony.unicopia.ability.magic.spell.ProjectileSpell; +import com.minelittlepony.unicopia.ability.magic.spell.Situation; +import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; +import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; +import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; +import com.minelittlepony.unicopia.util.RayTraceHelper; + +import net.minecraft.block.BlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.FallingBlockEntity; +import net.minecraft.predicate.entity.EntityPredicates; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.hit.EntityHitResult; +import net.minecraft.util.hit.HitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class CatapultSpell extends AbstractSpell implements ProjectileSpell { + public static final SpellTraits DEFAULT_TRAITS = new SpellTraits.Builder() + .with(Trait.FOCUS, 50) + .with(Trait.KNOWLEDGE, 1) + .with(Trait.EARTH, 60) + .with(Trait.STRENGTH, 50) + .build(); + + private static final float HORIZONTAL_VARIANCE = 0.25F; + private static final float MAX_STRENGTH = 120; + + protected CatapultSpell(SpellType type, SpellTraits traits) { + super(type, traits); + } + + @Override + public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) { + if (!projectile.isClient()) { + createBlockEntity(projectile.world, pos, e -> apply(projectile, e)); + } + } + + @Override + public void onImpact(MagicProjectileEntity projectile, Entity entity) { + if (!projectile.isClient()) { + apply(projectile, entity); + } + } + + @Override + public boolean tick(Caster caster, Situation situation) { + if (situation == Situation.PROJECTILE) { + return true; + } + + getTarget(caster, e -> apply(caster, e)); + return situation == Situation.PROJECTILE; + } + + protected void apply(Caster caster, Entity e) { + Vec3d vel = caster.getEntity().getVelocity(); + e.addVelocity( + ((caster.getWorld().random.nextFloat() * HORIZONTAL_VARIANCE) - HORIZONTAL_VARIANCE + vel.x * 0.8F) * 0.1F, + 0.1F + (getTraits().get(Trait.STRENGTH, -MAX_STRENGTH, MAX_STRENGTH) - 50) / 16D, + ((caster.getWorld().random.nextFloat() * HORIZONTAL_VARIANCE) - HORIZONTAL_VARIANCE + vel.z * 0.8F) * 0.1F + ); + e.world.spawnEntity(e); + } + + protected void getTarget(Caster caster, Consumer apply) { + if (caster.isClient()) { + return; + } + + double maxDistance = 2 + (getTraits().get(Trait.FOCUS) - 50) * 8; + + HitResult ray = RayTraceHelper.doTrace(caster.getMaster(), maxDistance, 1, EntityPredicates.EXCEPT_SPECTATOR).getResult(); + + if (ray.getType() == HitResult.Type.ENTITY) { + EntityHitResult result = (EntityHitResult)ray; + Optional.ofNullable(result.getEntity()).ifPresent(apply); + } else if (ray.getType() == HitResult.Type.BLOCK) { + createBlockEntity(caster.getWorld(), ((BlockHitResult)ray).getBlockPos(), apply); + } + } + + static void createBlockEntity(World world, BlockPos bpos, Consumer apply) { + Vec3d pos = Vec3d.ofBottomCenter(bpos); + FallingBlockEntity e = new FallingBlockEntity(world, pos.x, pos.y, pos.z, world.getBlockState(bpos)); + world.removeBlock(bpos, true); + e.setOnGround(false); + e.timeFalling = Integer.MIN_VALUE; + + apply.accept(e); + world.spawnEntity(e); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/InfernoSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/InfernoSpell.java index 5eca5cc6..3bf3ec26 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/InfernoSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/InfernoSpell.java @@ -16,6 +16,9 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +/** + * Converts surrounding blocks and entities into their nether equivalent + */ public class InfernoSpell extends FireSpell { protected InfernoSpell(SpellType type, SpellTraits traits) { 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 47f7e03c..97b6fd12 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 @@ -56,8 +56,9 @@ public final class SpellType implements Affine, SpellPredicate< public static final SpellType DRAINING = register("draining", Affinity.BAD, 0xe308ab, true, SiphoningSpell::new); public static final SpellType REVEALING = register("reveal", Affinity.GOOD, 0x5CE81F, true, RevealingSpell::new); public static final SpellType AWKWARD = register("awkward", Affinity.GOOD, 0xE1239C, true, AwkwardSpell::new); - public static final SpellType TRANSFORMATION = register("transformation", Affinity.NEUTRAL, 0x3A59AA, true, TransformationSpell::new); + public static final SpellType TRANSFORMATION = register("transformation", Affinity.GOOD, 0x3A59AA, true, TransformationSpell::new); public static final SpellType FEATHER_FALL = register("feather_fall", Affinity.GOOD, 0x00EEFF, true, FeatherFallSpell.DEFAULT_TRAITS, FeatherFallSpell::new); + public static final SpellType CATAPULT = register("catapult", Affinity.GOOD, 0x33FF00, true, CatapultSpell.DEFAULT_TRAITS, CatapultSpell::new); private final Identifier id; private final Affinity affinity; diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/SpellTraits.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/SpellTraits.java index 6439baee..edc2bc2a 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/SpellTraits.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/SpellTraits.java @@ -11,6 +11,7 @@ import java.util.Map.Entry; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -50,13 +51,21 @@ public final class SpellTraits implements Iterable> { return factor == 0 ? EMPTY : map(v -> v * factor); } + public SpellTraits add(float amount) { + return amount == 0 ? this : map(v -> v + amount); + } + public SpellTraits map(Function function) { + return map((k, v) -> function.apply(v)); + } + + public SpellTraits map(BiFunction function) { if (isEmpty()) { return this; } Map newMap = new EnumMap<>(traits); - newMap.entrySet().forEach(entry -> entry.setValue(function.apply(entry.getValue()))); + newMap.entrySet().forEach(entry -> entry.setValue(function.apply(entry.getKey(), entry.getValue()))); return fromEntries(newMap.entrySet().stream()).orElse(EMPTY); }