Flightly fix the logic for when the cast abilities should fail

This commit is contained in:
Sollace 2021-03-02 19:38:54 +02:00
parent c5fdb9167f
commit a50cc0d117
4 changed files with 111 additions and 45 deletions

View file

@ -1,6 +1,5 @@
package com.minelittlepony.unicopia.ability;
import java.util.Optional;
import java.util.Random;
import javax.annotation.Nullable;
@ -20,8 +19,9 @@ import net.minecraft.item.ItemStack;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.Pair;
import net.minecraft.util.TypedActionResult;
import net.minecraft.util.math.Vec3d;
/**
@ -48,7 +48,21 @@ public class UnicornCastingAbility implements Ability<Hit> {
@Override
@Nullable
public Hit tryActivate(Pony player) {
return getCostEstimate(player) <= player.getMagicalReserves().getMana().get() ? Hit.INSTANCE : null;
float manaLevel = player.getMagicalReserves().getMana().get();
TypedActionResult<ItemStack> amulet = getAmulet(player);
if (amulet.getResult().isAccepted()) {
return Hit.of(manaLevel > 0 && ((AmuletItem)amulet.getValue().getItem()).canCharge(amulet.getValue()));
}
ActionResult spell = getNewSpell(player).getResult();
if (spell != ActionResult.PASS) {
return Hit.of(spell != ActionResult.FAIL && manaLevel > 4F);
}
return Hit.of(manaLevel > (player.hasSpell() ? 2F : 4F));
}
@Override
@ -58,62 +72,87 @@ public class UnicornCastingAbility implements Ability<Hit> {
@Override
public double getCostEstimate(Pony player) {
return getAmulet(player)
.map(pair -> Math.min(player.getMagicalReserves().getMana().get(), pair.getLeft().getChargeRemainder(pair.getRight())))
.orElseGet(() -> player.hasSpell() && getNewSpell(player).isPresent() ? 4F : 2F);
TypedActionResult<ItemStack> amulet = getAmulet(player);
if (amulet.getResult().isAccepted()) {
float manaLevel = player.getMagicalReserves().getMana().get();
return Math.min(manaLevel, ((AmuletItem)amulet.getValue().getItem()).getChargeRemainder(amulet.getValue()));
}
if (getNewSpell(player).getResult() == ActionResult.CONSUME) {
return 4F;
}
if (player.hasSpell()) {
return 2F;
}
return 4F;
}
@Override
public void apply(Pony player, Hit data) {
getAmulet(player).filter(pair -> {
float amount = -Math.min(player.getMagicalReserves().getMana().get(), pair.getLeft().getChargeRemainder(pair.getRight()));
TypedActionResult<ItemStack> amulet = getAmulet(player);
if (amulet.getResult().isAccepted()) {
ItemStack stack = amulet.getValue();
AmuletItem item = (AmuletItem)stack.getItem();
if (item.canCharge(stack)) {
float amount = -Math.min(player.getMagicalReserves().getMana().get(), item.getChargeRemainder(stack));
if (amount < 0) {
AmuletItem.consumeEnergy(pair.getRight(), amount);
AmuletItem.consumeEnergy(stack, amount);
player.getMagicalReserves().getMana().add(amount * player.getMagicalReserves().getMana().getMax());
player.getWorld().playSoundFromEntity(null, player.getMaster(), SoundEvents.BLOCK_END_PORTAL_FRAME_FILL, SoundCategory.PLAYERS, 1, 1);
}
return true;
}).orElseGet(() -> {
Optional<Spell> newSpell = getNewSpell(player);
}
} else {
TypedActionResult<Spell> newSpell = getNewSpell(player);
if (newSpell.getResult() != ActionResult.FAIL) {
@Nullable
Spell spell = player.hasSpell() ? newSpell.orElse(null) : newSpell.orElseGet(SpellType.SHIELD::create);
Spell spell = newSpell.getValue();
if (!player.hasSpell() && spell == null) {
spell = SpellType.SHIELD.create();
}
player.subtractEnergyCost(spell == null ? 2 : 4);
player.setSpell(spell);
return null;
});
}
}
}
private Optional<Pair<AmuletItem, ItemStack>> getAmulet(Pony player) {
private TypedActionResult<ItemStack> getAmulet(Pony player) {
ItemStack stack = player.getMaster().getStackInHand(Hand.MAIN_HAND);
if (stack.getItem() instanceof AmuletItem) {
AmuletItem amulet = (AmuletItem)stack.getItem();
if (amulet.canCharge(stack)) {
return Optional.of(new Pair<>(amulet, stack));
}
if (((AmuletItem)stack.getItem()).isChargable()) {
return TypedActionResult.consume(stack);
}
return Optional.empty();
return TypedActionResult.success(stack);
}
private Optional<Spell> getNewSpell(Pony player) {
return TypedActionResult.pass(stack);
}
private TypedActionResult<Spell> getNewSpell(Pony player) {
final SpellType<?> current = player.hasSpell() ? player.getSpell(true).getType() : null;
return Streams.stream(player.getMaster().getItemsHand())
.flatMap(stack -> GemstoneItem.consumeSpell(stack, player.getMaster(), current, i -> i instanceof Attached))
.findFirst();
.filter(GemstoneItem::isEnchanted)
.map(stack -> GemstoneItem.consumeSpell(stack, player.getMaster(), current, i -> i instanceof Attached))
.findFirst()
.orElse(TypedActionResult.<Spell>pass(null));
}
@Override
public void preApply(Pony player, AbilitySlot slot) {
player.getMagicalReserves().getEnergy().multiply(3.3F);
if (getAmulet(player).isPresent()) {
if (getAmulet(player).getResult() == ActionResult.CONSUME) {
Vec3d eyes = player.getMaster().getCameraPosVec(1);
float i = player.getAbilities().getStat(slot).getFillProgress();

View file

@ -1,17 +1,20 @@
package com.minelittlepony.unicopia.ability;
import java.util.Optional;
import javax.annotation.Nullable;
import com.google.common.collect.Streams;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.ability.data.Hit;
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.player.Pony;
import com.minelittlepony.unicopia.item.GemstoneItem;
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Identifier;
import net.minecraft.util.TypedActionResult;
/**
* A magic casting ability for unicorns.
@ -45,7 +48,7 @@ public class UnicornProjectileAbility implements Ability<Hit> {
@Override
public Hit tryActivate(Pony player) {
return Hit.INSTANCE;
return Hit.of(getNewSpell(player).getResult() != ActionResult.FAIL);
}
@Override
@ -60,15 +63,27 @@ public class UnicornProjectileAbility implements Ability<Hit> {
@Override
public void apply(Pony player, Hit data) {
player.subtractEnergyCost(getCostEstimate(player));
getThrown(player).orElseGet(SpellType.VORTEX::create).toss(player);
TypedActionResult<Spell> thrown = getNewSpell(player);
if (thrown.getResult() != ActionResult.FAIL) {
@Nullable
Thrown spell = (Thrown)thrown.getValue();
if (spell == null) {
spell = SpellType.VORTEX.create();
}
private Optional<Thrown> getThrown(Pony player) {
player.subtractEnergyCost(getCostEstimate(player));
spell.toss(player);
}
}
private TypedActionResult<Spell> getNewSpell(Pony player) {
return Streams.stream(player.getMaster().getItemsHand())
.flatMap(stack -> GemstoneItem.consumeSpell(stack, player.getMaster(), null, i -> i instanceof Thrown))
.map(Thrown.class::cast)
.findFirst();
.filter(GemstoneItem::isEnchanted)
.map(stack -> GemstoneItem.consumeSpell(stack, player.getMaster(), null, i -> i instanceof Thrown))
.findFirst()
.orElse(TypedActionResult.<Spell>pass(null));
}
@Override

View file

@ -7,6 +7,10 @@ public class Hit {
public static final Hit INSTANCE = new Hit();
public static final Serializer<Hit> SERIALIZER = buf -> INSTANCE;
public static Hit of(boolean value) {
return value ? INSTANCE : null;
}
protected Hit() {
}

View file

@ -3,7 +3,6 @@ package com.minelittlepony.unicopia.item;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
import java.util.stream.Stream;
import javax.annotation.Nullable;
@ -19,7 +18,9 @@ import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import net.minecraft.util.TypedActionResult;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.world.World;
@ -67,20 +68,27 @@ public class GemstoneItem extends Item {
return super.getName();
}
public static Stream<Spell> consumeSpell(ItemStack stack, PlayerEntity player, @Nullable SpellType<?> exclude, Predicate<Spell> test) {
public static TypedActionResult<Spell> consumeSpell(ItemStack stack, PlayerEntity player, @Nullable SpellType<?> exclude, Predicate<Spell> test) {
if (!isEnchanted(stack)) {
return TypedActionResult.pass(null);
}
SpellType<Spell> key = GemstoneItem.getSpellKey(stack);
if (Objects.equals(key, exclude)) {
return Stream.empty();
return TypedActionResult.fail(null);
}
Spell spell = key.create(getAffinity(stack));
if (spell == null || !test.test(spell)) {
return Stream.empty();
return TypedActionResult.fail(null);
}
if (!player.world.isClient) {
player.swingHand(player.getStackInHand(Hand.OFF_HAND) == stack ? Hand.OFF_HAND : Hand.MAIN_HAND);
if (stack.getCount() == 1) {
GemstoneItem.unenchanted(stack);
} else {
@ -88,7 +96,7 @@ public class GemstoneItem extends Item {
}
}
return Stream.of(spell);
return TypedActionResult.consume(spell);
}
public static boolean isEnchanted(ItemStack stack) {