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

View file

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

View file

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

View file

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