mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-07 22:16:44 +01:00
Clean up the abilities code
This commit is contained in:
parent
3ed4ec746c
commit
3b16930e3b
24 changed files with 292 additions and 355 deletions
|
@ -2,15 +2,13 @@ package com.minelittlepony.unicopia.ability;
|
|||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.util.Util;
|
||||
|
||||
public interface Ability<T extends Hit> {
|
||||
/**
|
||||
|
@ -28,10 +26,42 @@ public interface Ability<T extends Hit> {
|
|||
*/
|
||||
int getCooldownTime(Pony player);
|
||||
|
||||
/**
|
||||
* The icon representing this ability on the UI and HUD.
|
||||
*/
|
||||
default Identifier getIcon(Pony player) {
|
||||
return getId().withPath(p -> "textures/gui/ability/" + p + ".png");
|
||||
}
|
||||
|
||||
default int getColor(Pony player) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* The display name for this ability.
|
||||
*/
|
||||
default Text getName(Pony player) {
|
||||
return Text.translatable(getTranslationKey());
|
||||
}
|
||||
|
||||
default String getTranslationKey() {
|
||||
return Util.createTranslationKey("ability", getId());
|
||||
}
|
||||
|
||||
default Identifier getId() {
|
||||
return Abilities.REGISTRY.getId(this);
|
||||
}
|
||||
|
||||
default boolean activateOnEarlyRelease() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given race is permitted to use this ability
|
||||
* @param playerSpecies The player's species
|
||||
*/
|
||||
boolean canUse(Race playerSpecies);
|
||||
|
||||
/**
|
||||
* Called when an ability is about to be triggered. This event occurs on both the client and server so check {@code Pony#isClient} if you need to know which one you're on.
|
||||
* <p>
|
||||
|
@ -40,86 +70,32 @@ public interface Ability<T extends Hit> {
|
|||
* @return True if the event has been handled.
|
||||
*/
|
||||
default boolean onQuickAction(Pony player, ActivationType type, Optional<T> data) {
|
||||
return onQuickAction(player, type);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
default boolean onQuickAction(Pony player, ActivationType type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on the client to get any data required for the quick action.
|
||||
*
|
||||
* @param player The player
|
||||
* @param type The type of quick event being triggered
|
||||
* @return The data to pass on to the quick event handler
|
||||
*/
|
||||
default Optional<T> prepareQuickAction(Pony player, ActivationType type) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to check preconditions for activating the ability.
|
||||
*
|
||||
* @param w The world
|
||||
* @param player The player
|
||||
* @return True to allow activation
|
||||
* Gets the serializer to use for reading data over the network.
|
||||
*/
|
||||
default boolean canActivate(World w, Pony player) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given race is permitted to use this ability
|
||||
* @param playerSpecies The player's species
|
||||
*/
|
||||
boolean canUse(Race playerSpecies);
|
||||
|
||||
@Deprecated
|
||||
@Nullable
|
||||
T tryActivate(Pony player);
|
||||
|
||||
/**
|
||||
* Called on the client to activate the ability.
|
||||
*
|
||||
* @param player The player activating the ability
|
||||
* @return Data to be sent, or null if activation failed
|
||||
*/
|
||||
default Optional<T> prepare(Pony player) {
|
||||
return Optional.ofNullable(tryActivate(player));
|
||||
}
|
||||
|
||||
Hit.Serializer<T> getSerializer();
|
||||
|
||||
/**
|
||||
* The icon representing this ability on the UI and HUD.
|
||||
*/
|
||||
default Identifier getIcon(Pony player) {
|
||||
Identifier id = Abilities.REGISTRY.getId(this);
|
||||
return new Identifier(id.getNamespace(), "textures/gui/ability/" + id.getPath() + ".png");
|
||||
}
|
||||
|
||||
default Text getName(Pony player) {
|
||||
return getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* The display name for this ability.
|
||||
*/
|
||||
default Text getName() {
|
||||
return Text.translatable(getTranslationKey());
|
||||
}
|
||||
|
||||
default String getTranslationKey() {
|
||||
Identifier id = Abilities.REGISTRY.getId(this);
|
||||
return "ability." + id.getNamespace() + "." + id.getPath().replace('/', '.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Server-side counterpart to canActivate.
|
||||
* Called on the client to get any data required to activate the ability.
|
||||
*
|
||||
* Called before applying to determine whether to cancel the command or not.
|
||||
* @param player The player activating the ability
|
||||
* @return Data to be sent, or Empty if activation failed
|
||||
*/
|
||||
default boolean canApply(Pony player, T data) {
|
||||
return true;
|
||||
}
|
||||
Optional<T> prepare(Pony player);
|
||||
|
||||
/**
|
||||
* Called to actually apply the ability.
|
||||
|
@ -127,18 +103,19 @@ public interface Ability<T extends Hit> {
|
|||
*
|
||||
* @param player The player that triggered the ability
|
||||
* @param data Data previously sent from the client
|
||||
* @return True if the ability succeeded. Returning false will cause an ability reset message to be sent to the client.
|
||||
*/
|
||||
void apply(Pony player, T data);
|
||||
boolean apply(Pony player, T data);
|
||||
|
||||
/**
|
||||
* Called every tick until the warmup timer runs out.
|
||||
* @param player The current player
|
||||
*/
|
||||
void preApply(Pony player, AbilitySlot slot);
|
||||
void warmUp(Pony player, AbilitySlot slot);
|
||||
|
||||
/**
|
||||
* Called every tick until the cooldown timer runs out.
|
||||
* @param player The current player
|
||||
*/
|
||||
void postApply(Pony player, AbilitySlot slot);
|
||||
void coolDown(Pony player, AbilitySlot slot);
|
||||
}
|
||||
|
|
|
@ -37,21 +37,10 @@ public class AbilityDispatcher implements Tickable, NbtSerialisable {
|
|||
Stat stat = getStat(slot);
|
||||
|
||||
if (stat.canSwitchStates()) {
|
||||
if (pressType == ActivationType.NONE || stat.getAbility(page).filter(ability -> !triggerQuickAction(ability, pressType)).isEmpty()) {
|
||||
stat.setActiveAbility(null);
|
||||
}
|
||||
stat.clear(pressType, page);
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends Hit> boolean triggerQuickAction(Ability<T> ability, ActivationType pressType) {
|
||||
Optional<T> data = ability.prepareQuickAction(player, pressType);
|
||||
if (ability.onQuickAction(player, pressType, data)) {
|
||||
Channel.CLIENT_PLAYER_ABILITY.sendToServer(new MsgPlayerAbility<>(ability, data, pressType));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Optional<Ability<?>> activate(AbilitySlot slot, long page) {
|
||||
Stat stat = getStat(slot);
|
||||
if (stat.canSwitchStates()) {
|
||||
|
@ -182,42 +171,42 @@ public class AbilityDispatcher implements Tickable, NbtSerialisable {
|
|||
}
|
||||
|
||||
public void tick() {
|
||||
getActiveAbility().ifPresent(this::activate);
|
||||
getActiveAbility().ifPresent(ability -> {
|
||||
if (warmup > 0) {
|
||||
warmup--;
|
||||
ability.warmUp(player, slot);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cooldown > 0 && cooldown-- > 0) {
|
||||
ability.coolDown(player, slot);
|
||||
|
||||
if (cooldown <= 0) {
|
||||
setActiveAbility(null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
tryFire(ability);
|
||||
});
|
||||
}
|
||||
|
||||
private <T extends Hit> void activate(Ability<T> ability) {
|
||||
if (warmup > 0) {
|
||||
warmup--;
|
||||
ability.preApply(player, slot);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cooldown > 0 && cooldown-- > 0) {
|
||||
ability.postApply(player, slot);
|
||||
|
||||
if (cooldown <= 0) {
|
||||
setActiveAbility(null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
private <T extends Hit> void tryFire(Ability<T> ability) {
|
||||
if (triggered) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ability.canActivate(player.asWorld(), player)) {
|
||||
triggered = true;
|
||||
setCooldown(ability.getCooldownTime(player));
|
||||
triggered = true;
|
||||
setCooldown(ability.getCooldownTime(player));
|
||||
|
||||
if (player.isClientPlayer()) {
|
||||
Optional<T> data = ability.prepare(player);
|
||||
if (player.isClientPlayer()) {
|
||||
Optional<T> data = ability.prepare(player);
|
||||
|
||||
if (data.isPresent()) {
|
||||
Channel.CLIENT_PLAYER_ABILITY.sendToServer(new MsgPlayerAbility<>(ability, data, ActivationType.NONE));
|
||||
} else {
|
||||
player.asEntity().playSound(USounds.GUI_ABILITY_FAIL, 1, 1);
|
||||
setCooldown(0);
|
||||
}
|
||||
if (data.isPresent()) {
|
||||
Channel.CLIENT_PLAYER_ABILITY.sendToServer(new MsgPlayerAbility<>(ability, data, ActivationType.NONE));
|
||||
} else {
|
||||
player.asEntity().playSound(USounds.GUI_ABILITY_FAIL, 1, 1);
|
||||
setCooldown(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -235,6 +224,26 @@ public class AbilityDispatcher implements Tickable, NbtSerialisable {
|
|||
return Optional.ofNullable(found.get((int)Math.min(found.size() - 1, page)));
|
||||
}
|
||||
|
||||
public void clear(ActivationType pressType, long page) {
|
||||
if (pressType == ActivationType.NONE
|
||||
|| getAbility(page).filter(ability -> !triggerQuickAction(ability, pressType)).isEmpty()) {
|
||||
if (warmup > 0) {
|
||||
getActiveAbility().filter(Ability::activateOnEarlyRelease).ifPresentOrElse(this::tryFire, () -> setActiveAbility(null));
|
||||
} else {
|
||||
setActiveAbility(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends Hit> boolean triggerQuickAction(Ability<T> ability, ActivationType pressType) {
|
||||
Optional<T> data = ability.prepareQuickAction(player, pressType);
|
||||
if (ability.onQuickAction(player, pressType, data)) {
|
||||
Channel.CLIENT_PLAYER_ABILITY.sendToServer(new MsgPlayerAbility<>(ability, data, pressType));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public long getMaxPage() {
|
||||
return Abilities.BY_SLOT_AND_COMPOSITE_RACE.apply(slot, player.getCompositeRace()).size();
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ abstract class AbstractSpellCastingAbility implements Ability<Hit> {
|
|||
gemSpell.getValue().type().getName().copy().formatted(gemSpell.getValue().type().getAffinity().getColor())
|
||||
);
|
||||
}
|
||||
return getName();
|
||||
return Ability.super.getName(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -64,7 +64,7 @@ abstract class AbstractSpellCastingAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void postApply(Pony player, AbilitySlot slot) {
|
||||
public void coolDown(Pony player, AbilitySlot slot) {
|
||||
player.spawnParticles(MagicParticleEffect.UNICORN, 5);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package com.minelittlepony.unicopia.ability;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.minelittlepony.unicopia.AwaitTickQueue;
|
||||
import com.minelittlepony.unicopia.EquinePredicates;
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.USounds;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.ability.data.Numeric;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||
import com.minelittlepony.unicopia.advancement.UCriteria;
|
||||
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
|
||||
|
@ -23,7 +25,7 @@ import net.minecraft.util.math.random.Random;
|
|||
* A magic casting ability for unicorns.
|
||||
* (only shields for now)
|
||||
*/
|
||||
public class BatEeeeAbility implements Ability<Hit> {
|
||||
public class BatEeeeAbility implements Ability<Numeric> {
|
||||
|
||||
@Override
|
||||
public int getWarmupTime(Pony player) {
|
||||
|
@ -46,17 +48,17 @@ public class BatEeeeAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Hit tryActivate(Pony player) {
|
||||
return Hit.INSTANCE;
|
||||
public Optional<Numeric> prepare(Pony player) {
|
||||
return Numeric.of(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hit.Serializer<Hit> getSerializer() {
|
||||
return Hit.SERIALIZER;
|
||||
public Numeric.Serializer<Numeric> getSerializer() {
|
||||
return Numeric.SERIALIZER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Pony player, Hit data) {
|
||||
public boolean apply(Pony player, Numeric data) {
|
||||
Random rng = player.asWorld().random;
|
||||
int count = 1 + rng.nextInt(10);
|
||||
|
||||
|
@ -105,14 +107,16 @@ public class BatEeeeAbility implements Ability<Hit> {
|
|||
if (total >= 20) {
|
||||
UCriteria.SCREECH_TWENTY_MOBS.trigger(player.asEntity());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preApply(Pony player, AbilitySlot slot) {
|
||||
public void warmUp(Pony player, AbilitySlot slot) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postApply(Pony player, AbilitySlot slot) {
|
||||
public void coolDown(Pony player, AbilitySlot slot) {
|
||||
for (int i = 0; i < 20; i++) {
|
||||
player.addParticle(ParticleTypes.BUBBLE_POP, player.getPhysics().getHeadPosition().toCenterPos(), VecHelper.supply(() -> player.asWorld().getRandom().nextGaussian() - 0.5));
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.minelittlepony.unicopia.ability;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.ability.data.Multi;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
|
@ -34,17 +36,16 @@ public class BatPonyHangAbility implements Ability<Multi> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Multi tryActivate(Pony player) {
|
||||
public Optional<Multi> prepare(Pony player) {
|
||||
|
||||
if (player.isHanging()) {
|
||||
return new Multi(BlockPos.ZERO, 0);
|
||||
return Optional.of(new Multi(BlockPos.ZERO, 0));
|
||||
}
|
||||
|
||||
return TraceHelper.findBlock(player.asEntity(), 5, 1)
|
||||
.map(BlockPos::down)
|
||||
.filter(player::canHangAt)
|
||||
.map(pos -> new Multi(pos, 1))
|
||||
.orElse(null);
|
||||
.map(pos -> new Multi(pos, 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -53,22 +54,24 @@ public class BatPonyHangAbility implements Ability<Multi> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void apply(Pony player, Multi data) {
|
||||
if (data.hitType == 0 && player.isHanging()) {
|
||||
public boolean apply(Pony player, Multi data) {
|
||||
if (data.hitType() == 0 && player.isHanging()) {
|
||||
player.stopHanging();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (data.hitType == 1 && player.canHangAt(data.pos())) {
|
||||
player.startHanging(data.pos());
|
||||
if (data.hitType() == 1 && player.canHangAt(data.pos().pos())) {
|
||||
player.startHanging(data.pos().pos());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preApply(Pony player, AbilitySlot slot) {
|
||||
public void warmUp(Pony player, AbilitySlot slot) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postApply(Pony player, AbilitySlot slot) {
|
||||
public void coolDown(Pony player, AbilitySlot slot) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.minelittlepony.unicopia.ability;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
|
@ -41,7 +42,7 @@ public class CarryAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Hit tryActivate(Pony player) {
|
||||
public Optional<Hit> prepare(Pony player) {
|
||||
return Hit.INSTANCE;
|
||||
}
|
||||
|
||||
|
@ -57,7 +58,7 @@ public class CarryAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean onQuickAction(Pony player, ActivationType type) {
|
||||
public boolean onQuickAction(Pony player, ActivationType type, Optional<Hit> data) {
|
||||
|
||||
if (type == ActivationType.TAP && player.getPhysics().isFlying()) {
|
||||
player.getPhysics().dashForward((float)player.asWorld().random.nextTriangular(1, 0.3F));
|
||||
|
@ -68,7 +69,7 @@ public class CarryAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void apply(Pony iplayer, Hit data) {
|
||||
public boolean apply(Pony iplayer, Hit data) {
|
||||
PlayerEntity player = iplayer.asEntity();
|
||||
LivingEntity rider = findRider(player, iplayer.asWorld());
|
||||
|
||||
|
@ -90,14 +91,15 @@ public class CarryAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
Living.transmitPassengers(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preApply(Pony player, AbilitySlot slot) {
|
||||
public void warmUp(Pony player, AbilitySlot slot) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postApply(Pony player, AbilitySlot slot) {
|
||||
public void coolDown(Pony player, AbilitySlot slot) {
|
||||
}
|
||||
|
||||
public interface IPickupImmuned {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package com.minelittlepony.unicopia.ability;
|
||||
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.EquinePredicates;
|
||||
|
@ -25,19 +27,16 @@ public class ChangelingDisguiseAbility extends ChangelingFeedAbility {
|
|||
|
||||
@Nullable
|
||||
@Override
|
||||
public Hit tryActivate(Pony player) {
|
||||
if (player.asEntity().isCreative() || player.getMagicalReserves().getMana().getPercentFill() >= 0.9F) {
|
||||
return Hit.INSTANCE;
|
||||
}
|
||||
return null;
|
||||
public Optional<Hit> prepare(Pony player) {
|
||||
return Hit.of(player.asEntity().isCreative() || player.getMagicalReserves().getMana().getPercentFill() >= 0.9F);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Pony iplayer, Hit data) {
|
||||
public boolean apply(Pony iplayer, Hit data) {
|
||||
PlayerEntity player = iplayer.asEntity();
|
||||
|
||||
if (!player.isCreative() && iplayer.getMagicalReserves().getMana().getPercentFill() < 0.9F) {
|
||||
return;
|
||||
if (prepare(iplayer).isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Trace trace = Trace.create(player, 10, 1, EquinePredicates.VALID_FOR_DISGUISE);
|
||||
|
@ -61,16 +60,17 @@ public class ChangelingDisguiseAbility extends ChangelingFeedAbility {
|
|||
|
||||
player.calculateDimensions();
|
||||
iplayer.setDirty();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preApply(Pony player, AbilitySlot slot) {
|
||||
public void warmUp(Pony player, AbilitySlot slot) {
|
||||
player.getMagicalReserves().getEnergy().add(20);
|
||||
player.spawnParticles(UParticles.CHANGELING_MAGIC, 5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postApply(Pony player, AbilitySlot slot) {
|
||||
public void coolDown(Pony player, AbilitySlot slot) {
|
||||
player.getMagicalReserves().getEnergy().set(0);
|
||||
player.spawnParticles(UParticles.CHANGELING_MAGIC, 5);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.minelittlepony.unicopia.ability;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
@ -51,14 +52,8 @@ public class ChangelingFeedAbility implements Ability<Hit> {
|
|||
|
||||
@Nullable
|
||||
@Override
|
||||
public Hit tryActivate(Pony player) {
|
||||
if (canFeed(player)) {
|
||||
if (!getTargets(player).isEmpty()) {
|
||||
return Hit.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
public Optional<Hit> prepare(Pony player) {
|
||||
return Hit.of(canFeed(player) && !getTargets(player).isEmpty());
|
||||
}
|
||||
|
||||
private boolean canFeed(Pony player) {
|
||||
|
@ -97,9 +92,9 @@ public class ChangelingFeedAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void apply(Pony iplayer, Hit data) {
|
||||
public boolean apply(Pony iplayer, Hit data) {
|
||||
if (!canFeed(iplayer)) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
PlayerEntity player = iplayer.asEntity();
|
||||
|
@ -131,6 +126,8 @@ public class ChangelingFeedAbility implements Ability<Hit> {
|
|||
} else {
|
||||
iplayer.playSound(SoundEvents.ENTITY_GENERIC_DRINK, 0.1F, iplayer.getRandomPitch());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public float drainFrom(Pony changeling, LivingEntity living) {
|
||||
|
@ -167,12 +164,12 @@ public class ChangelingFeedAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void preApply(Pony player, AbilitySlot slot) {
|
||||
public void warmUp(Pony player, AbilitySlot slot) {
|
||||
player.getMagicalReserves().getExertion().add(6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postApply(Pony player, AbilitySlot slot) {
|
||||
public void coolDown(Pony player, AbilitySlot slot) {
|
||||
if (player.asWorld().random.nextInt(10) == 0) {
|
||||
player.spawnParticles(ParticleTypes.HEART, 1);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.minelittlepony.unicopia.ability;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.ability.data.Pos;
|
||||
|
@ -35,8 +37,8 @@ public class EarthPonyGrowAbility implements Ability<Pos> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Pos tryActivate(Pony player) {
|
||||
return TraceHelper.findBlock(player.asEntity(), 3, 1).map(Pos::new).orElse(null);
|
||||
public Optional<Pos> prepare(Pony player) {
|
||||
return TraceHelper.findBlock(player.asEntity(), 3, 1).map(Pos::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -50,7 +52,7 @@ public class EarthPonyGrowAbility implements Ability<Pos> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void apply(Pony player, Pos data) {
|
||||
public boolean apply(Pony player, Pos data) {
|
||||
int count = 0;
|
||||
|
||||
for (BlockPos pos : BlockPos.iterate(
|
||||
|
@ -62,6 +64,7 @@ public class EarthPonyGrowAbility implements Ability<Pos> {
|
|||
if (count > 0) {
|
||||
player.subtractEnergyCost(count / 5D);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected int applySingle(World w, BlockState state, BlockPos pos) {
|
||||
|
@ -77,7 +80,7 @@ public class EarthPonyGrowAbility implements Ability<Pos> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void preApply(Pony player, AbilitySlot slot) {
|
||||
public void warmUp(Pony player, AbilitySlot slot) {
|
||||
player.getMagicalReserves().getExertion().add(30);
|
||||
|
||||
if (player.asWorld().isClient()) {
|
||||
|
@ -86,7 +89,7 @@ public class EarthPonyGrowAbility implements Ability<Pos> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void postApply(Pony player, AbilitySlot slot) {
|
||||
public void coolDown(Pony player, AbilitySlot slot) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,11 +113,11 @@ public class EarthPonyKickAbility implements Ability<Pos> {
|
|||
|
||||
@Nullable
|
||||
@Override
|
||||
public Pos tryActivate(Pony player) {
|
||||
public Optional<Pos> prepare(Pony player) {
|
||||
return TraceHelper.findBlock(player.asEntity(), 6 * getKickDirection(player), 1)
|
||||
.filter(pos -> TreeType.at(pos, player.asWorld()) != TreeType.NONE)
|
||||
.map(Pos::new)
|
||||
.orElseGet(() -> getDefaultKickLocation(player));
|
||||
.or(() -> Optional.of(getDefaultKickLocation(player)));
|
||||
}
|
||||
|
||||
private int getKickDirection(Pony player) {
|
||||
|
@ -133,33 +133,26 @@ public class EarthPonyKickAbility implements Ability<Pos> {
|
|||
return new Pos(BlockPos.ofFloored(player.getOriginVector().add(kickVector)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApply(Pony player, Pos data) {
|
||||
BlockPos pos = data.pos();
|
||||
TreeType tree = TreeType.at(pos, player.asWorld());
|
||||
|
||||
return tree == TreeType.NONE || tree.findBase(player.asWorld(), pos)
|
||||
.map(base -> tree.countBlocks(player.asWorld(), pos) > 0)
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hit.Serializer<Pos> getSerializer() {
|
||||
return Pos.SERIALIZER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Pony iplayer, Pos data) {
|
||||
public boolean apply(Pony iplayer, Pos data) {
|
||||
|
||||
BlockPos pos = data.pos();
|
||||
TreeType tree = TreeType.at(pos, iplayer.asWorld());
|
||||
|
||||
if (tree == TreeType.NONE || tree.findBase(iplayer.asWorld(), pos)
|
||||
.map(base -> tree.countBlocks(iplayer.asWorld(), pos) > 0)
|
||||
.orElse(false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
iplayer.setAnimation(Animation.KICK, Animation.Recipient.ANYONE);
|
||||
iplayer.subtractEnergyCost(tree == TreeType.NONE ? 1 : 3);
|
||||
|
||||
if (tree == TreeType.NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
ParticleUtils.spawnParticle(iplayer.asWorld(), UParticles.GROUND_POUND, data.vec(), Vec3d.ZERO);
|
||||
|
||||
PlayerEntity player = iplayer.asEntity();
|
||||
|
@ -184,15 +177,17 @@ public class EarthPonyKickAbility implements Ability<Pos> {
|
|||
iplayer.subtractEnergyCost(cost / 7F);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preApply(Pony player, AbilitySlot slot) {
|
||||
public void warmUp(Pony player, AbilitySlot slot) {
|
||||
player.getMagicalReserves().getExertion().add(40);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postApply(Pony player, AbilitySlot slot) {
|
||||
public void coolDown(Pony player, AbilitySlot slot) {
|
||||
}
|
||||
|
||||
private int dropApples(PlayerEntity player, BlockPos pos) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.minelittlepony.unicopia.ability;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
|
@ -66,7 +68,7 @@ public class EarthPonyStompAbility implements Ability<Hit> {
|
|||
|
||||
@Nullable
|
||||
@Override
|
||||
public Hit tryActivate(Pony player) {
|
||||
public Optional<Hit> prepare(Pony player) {
|
||||
if (!player.asEntity().isOnGround()
|
||||
&& player.asEntity().getVelocity().y * player.getPhysics().getGravitySignum() < 0
|
||||
&& !player.asEntity().getAbilities().flying) {
|
||||
|
@ -74,7 +76,7 @@ public class EarthPonyStompAbility implements Ability<Hit> {
|
|||
return Hit.INSTANCE;
|
||||
}
|
||||
|
||||
return null;
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -92,7 +94,7 @@ public class EarthPonyStompAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void apply(Pony iplayer, Hit data) {
|
||||
public boolean apply(Pony iplayer, Hit data) {
|
||||
PlayerEntity player = iplayer.asEntity();
|
||||
|
||||
iplayer.setAnimation(Animation.STOMP, Animation.Recipient.ANYONE, 10);
|
||||
|
@ -152,6 +154,7 @@ public class EarthPonyStompAbility implements Ability<Hit> {
|
|||
|
||||
iplayer.subtractEnergyCost(rad);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void spawnEffectAround(Entity source, BlockPos center, double radius, double range) {
|
||||
|
@ -200,11 +203,11 @@ public class EarthPonyStompAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void preApply(Pony player, AbilitySlot slot) {
|
||||
public void warmUp(Pony player, AbilitySlot slot) {
|
||||
player.getMagicalReserves().getExertion().add(40);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postApply(Pony player, AbilitySlot slot) {
|
||||
public void coolDown(Pony player, AbilitySlot slot) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.minelittlepony.unicopia.ability;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
|
@ -38,13 +40,8 @@ public class PegasusCaptureStormAbility implements Ability<Hit> {
|
|||
|
||||
@Nullable
|
||||
@Override
|
||||
public Hit tryActivate(Pony player) {
|
||||
|
||||
if (!player.asEntity().isCreative() && player.getMagicalReserves().getMana().getPercentFill() < 0.2F) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Hit.INSTANCE;
|
||||
public Optional<Hit> prepare(Pony player) {
|
||||
return Hit.of(player.asEntity().isCreative() || player.getMagicalReserves().getMana().getPercentFill() >= 0.2F);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,7 +55,7 @@ public class PegasusCaptureStormAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void apply(Pony player, Hit data) {
|
||||
public boolean apply(Pony player, Hit data) {
|
||||
|
||||
World w = player.asWorld();
|
||||
ItemStack stack = player.asEntity().getStackInHand(Hand.MAIN_HAND);
|
||||
|
@ -106,6 +103,7 @@ public class PegasusCaptureStormAbility implements Ability<Hit> {
|
|||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void tell(Pony player, String translation) {
|
||||
|
@ -113,12 +111,12 @@ public class PegasusCaptureStormAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void preApply(Pony player, AbilitySlot slot) {
|
||||
public void warmUp(Pony player, AbilitySlot slot) {
|
||||
player.getMagicalReserves().getExertion().add(6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postApply(Pony player, AbilitySlot slot) {
|
||||
public void coolDown(Pony player, AbilitySlot slot) {
|
||||
player.spawnParticles(MagicParticleEffect.UNICORN, 5);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.minelittlepony.unicopia.ability;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
|
@ -29,8 +31,8 @@ public class PegasusFlightToggleAbility implements Ability<Hit> {
|
|||
|
||||
@Nullable
|
||||
@Override
|
||||
public Hit tryActivate(Pony player) {
|
||||
return player.asEntity().isCreative() || player.getPhysics().getFlightType().isGrounded() ? null : Hit.INSTANCE;
|
||||
public Optional<Hit> prepare(Pony player) {
|
||||
return Hit.of(!player.asEntity().isCreative() && !player.getPhysics().getFlightType().isGrounded());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -53,9 +55,9 @@ public class PegasusFlightToggleAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void apply(Pony player, Hit data) {
|
||||
if (tryActivate(player) == null) {
|
||||
return;
|
||||
public boolean apply(Pony player, Hit data) {
|
||||
if (prepare(player).isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
player.subtractEnergyCost(1);
|
||||
|
@ -69,14 +71,15 @@ public class PegasusFlightToggleAbility implements Ability<Hit> {
|
|||
}
|
||||
player.setDirty();
|
||||
player.setAnimation(Animation.SPREAD_WINGS, Animation.Recipient.ANYONE);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preApply(Pony player, AbilitySlot slot) {
|
||||
public void warmUp(Pony player, AbilitySlot slot) {
|
||||
player.getMagicalReserves().getExertion().add(6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postApply(Pony player, AbilitySlot slot) {
|
||||
public void coolDown(Pony player, AbilitySlot slot) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.minelittlepony.unicopia.ability;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
|
@ -12,7 +14,6 @@ import com.minelittlepony.unicopia.particle.OrientedBillboardParticleEffect;
|
|||
import com.minelittlepony.unicopia.particle.UParticles;
|
||||
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
/**
|
||||
* Pegasus ability to perform rainbooms
|
||||
|
@ -29,11 +30,6 @@ public class PegasusRainboomAbility implements Ability<Hit> {
|
|||
return 60;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canActivate(World w, Pony player) {
|
||||
return player.canUseSuperMove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race.canInteractWithClouds();
|
||||
|
@ -41,17 +37,8 @@ public class PegasusRainboomAbility implements Ability<Hit> {
|
|||
|
||||
@Nullable
|
||||
@Override
|
||||
public Hit tryActivate(Pony player) {
|
||||
|
||||
if (!player.asEntity().isCreative() && !player.canUseSuperMove()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (player.getPhysics().isFlying() && !SpellType.RAINBOOM.isOn(player)) {
|
||||
return Hit.INSTANCE;
|
||||
}
|
||||
|
||||
return null;
|
||||
public Optional<Hit> prepare(Pony player) {
|
||||
return Hit.of(player.canUseSuperMove() && player.getPhysics().isFlying() && !SpellType.RAINBOOM.isOn(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -65,7 +52,7 @@ public class PegasusRainboomAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean onQuickAction(Pony player, ActivationType type) {
|
||||
public boolean onQuickAction(Pony player, ActivationType type, Optional<Hit> data) {
|
||||
|
||||
if (type == ActivationType.TAP && player.getPhysics().isFlying() && player.getMagicalReserves().getMana().get() > 40) {
|
||||
player.getPhysics().dashForward((float)player.asWorld().random.nextTriangular(2.5F, 0.3F));
|
||||
|
@ -78,25 +65,26 @@ public class PegasusRainboomAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void apply(Pony player, Hit data) {
|
||||
public boolean apply(Pony player, Hit data) {
|
||||
|
||||
if (tryActivate(player) == null) {
|
||||
return;
|
||||
if (prepare(player).isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (player.consumeSuperMove()) {
|
||||
player.addParticle(new OrientedBillboardParticleEffect(UParticles.RAINBOOM_RING, player.getPhysics().getMotionAngle()), player.getOriginVector(), Vec3d.ZERO);
|
||||
SpellType.RAINBOOM.withTraits().apply(player, CastingMethod.INNATE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preApply(Pony player, AbilitySlot slot) {
|
||||
public void warmUp(Pony player, AbilitySlot slot) {
|
||||
player.getMagicalReserves().getExertion().add(6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postApply(Pony player, AbilitySlot slot) {
|
||||
public void coolDown(Pony player, AbilitySlot slot) {
|
||||
player.spawnParticles(MagicParticleEffect.UNICORN, 5);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.minelittlepony.unicopia.ability;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.minelittlepony.unicopia.*;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
|
@ -42,12 +42,8 @@ public class UnicornCastingAbility extends AbstractSpellCastingAbility {
|
|||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Hit tryActivate(Pony player) {
|
||||
if (!player.canCast()) {
|
||||
return null;
|
||||
}
|
||||
return Hit.of(player.getMagicalReserves().getMana().get() >= getCostEstimate(player));
|
||||
public Optional<Hit> prepare(Pony player) {
|
||||
return Hit.of(player.canCast() && player.getMagicalReserves().getMana().get() >= getCostEstimate(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -76,9 +72,9 @@ public class UnicornCastingAbility extends AbstractSpellCastingAbility {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void apply(Pony player, Hit data) {
|
||||
public boolean apply(Pony player, Hit data) {
|
||||
if (!player.canCast()) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
TypedActionResult<ItemStack> amulet = getAmulet(player);
|
||||
|
@ -123,6 +119,8 @@ public class UnicornCastingAbility extends AbstractSpellCastingAbility {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private TypedActionResult<ItemStack> getAmulet(Pony player) {
|
||||
|
@ -141,7 +139,7 @@ public class UnicornCastingAbility extends AbstractSpellCastingAbility {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void preApply(Pony player, AbilitySlot slot) {
|
||||
public void warmUp(Pony player, AbilitySlot slot) {
|
||||
player.getMagicalReserves().getExhaustion().multiply(3.3F);
|
||||
|
||||
if (getAmulet(player).getResult() == ActionResult.CONSUME) {
|
||||
|
|
|
@ -54,7 +54,7 @@ public class UnicornDispellAbility implements Ability<Pos> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean onQuickAction(Pony player, ActivationType type) {
|
||||
public boolean onQuickAction(Pony player, ActivationType type, Optional<Pos> data) {
|
||||
|
||||
if (player.getSpecies() != Race.CHANGELING) {
|
||||
if (type.getTapCount() > 1) {
|
||||
|
@ -84,16 +84,17 @@ public class UnicornDispellAbility implements Ability<Pos> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Pos tryActivate(Pony player) {
|
||||
return getTarget(player).map(Caster::getOrigin).map(Pos::new).orElse(null);
|
||||
public Optional<Pos> prepare(Pony player) {
|
||||
return getTarget(player).map(Caster::getOrigin).map(Pos::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Pony player, Pos data) {
|
||||
public boolean apply(Pony player, Pos data) {
|
||||
player.setAnimation(Animation.WOLOLO, Animation.Recipient.ANYONE);
|
||||
Caster.stream(VecHelper.findInRange(player.asEntity(), player.asWorld(), data.vec(), 3, EquinePredicates.IS_PLACED_SPELL).stream()).forEach(target -> {
|
||||
target.getSpellSlot().clear();
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
private Optional<Caster<?>> getTarget(Pony player) {
|
||||
|
@ -102,12 +103,12 @@ public class UnicornDispellAbility implements Ability<Pos> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void preApply(Pony player, AbilitySlot slot) {
|
||||
public void warmUp(Pony player, AbilitySlot slot) {
|
||||
player.getMagicalReserves().getExhaustion().multiply(3.3F);
|
||||
player.spawnParticles(MagicParticleEffect.UNICORN, 5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postApply(Pony player, AbilitySlot slot) {
|
||||
public void coolDown(Pony player, AbilitySlot slot) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,9 +23,9 @@ public class UnicornGroupTeleportAbility extends UnicornTeleportAbility {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void apply(Pony player, Pos data) {
|
||||
public boolean apply(Pony player, Pos data) {
|
||||
getComrades(player).forEach(teleportee -> teleport(player, teleportee, data));
|
||||
super.apply(player, data);
|
||||
return super.apply(player, data);
|
||||
}
|
||||
|
||||
private Stream<Caster<?>> getComrades(Pony player) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.minelittlepony.unicopia.ability;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.HomingSpell;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
||||
|
@ -25,7 +27,7 @@ public class UnicornProjectileAbility extends AbstractSpellCastingAbility {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Hit tryActivate(Pony player) {
|
||||
public Optional<Hit> prepare(Pony player) {
|
||||
return Hit.of(player.getCharms().getSpellInHand(false).getResult() != ActionResult.FAIL);
|
||||
}
|
||||
|
||||
|
@ -35,7 +37,7 @@ public class UnicornProjectileAbility extends AbstractSpellCastingAbility {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean onQuickAction(Pony player, ActivationType type) {
|
||||
public boolean onQuickAction(Pony player, ActivationType type, Optional<Hit> data) {
|
||||
if (type == ActivationType.DOUBLE_TAP) {
|
||||
if (!player.isClient()) {
|
||||
TypedActionResult<CustomisedSpellType<?>> thrown = player.getCharms().getSpellInHand(true);
|
||||
|
@ -54,7 +56,7 @@ public class UnicornProjectileAbility extends AbstractSpellCastingAbility {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void apply(Pony player, Hit data) {
|
||||
public boolean apply(Pony player, Hit data) {
|
||||
TypedActionResult<CustomisedSpellType<?>> thrown = player.getCharms().getSpellInHand(true);
|
||||
|
||||
if (thrown.getResult() != ActionResult.FAIL) {
|
||||
|
@ -69,11 +71,15 @@ public class UnicornProjectileAbility extends AbstractSpellCastingAbility {
|
|||
TraceHelper.findEntity(player.asEntity(), 600, 1).filter(((HomingSpell)spell)::setTarget).ifPresent(projectile::setHomingTarget);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preApply(Pony player, AbilitySlot slot) {
|
||||
public void warmUp(Pony player, AbilitySlot slot) {
|
||||
player.getMagicalReserves().getExhaustion().multiply(3.3F);
|
||||
player.spawnParticles(MagicParticleEffect.UNICORN, 5);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.minelittlepony.unicopia.ability;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.USounds;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
|
@ -32,8 +34,7 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
|||
|
||||
@Override
|
||||
public Identifier getIcon(Pony player) {
|
||||
Identifier id = Abilities.REGISTRY.getId(this);
|
||||
return new Identifier(id.getNamespace(), "textures/gui/ability/" + id.getPath() + (player.asEntity().isSneaking() ? "_far" : "_near") + ".png");
|
||||
return getId().withPath(p -> "textures/gui/ability/" + p + (player.asEntity().isSneaking() ? "_far" : "_near") + ".png");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -41,7 +42,7 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
|||
if (player.asEntity().isSneaking()) {
|
||||
return Text.translatable(getTranslationKey() + ".far");
|
||||
}
|
||||
return getName();
|
||||
return Ability.super.getName(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -61,12 +62,7 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
|||
|
||||
@Override
|
||||
public double getCostEstimate(Pony player) {
|
||||
Pos pos = tryActivate(player);
|
||||
|
||||
if (pos == null) {
|
||||
return 0;
|
||||
}
|
||||
return pos.distanceTo(player) / 10;
|
||||
return prepare(player).map(pos -> pos.distanceTo(player) / 10).orElse(0D);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -75,10 +71,10 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Pos tryActivate(Pony player) {
|
||||
public Optional<Pos> prepare(Pony player) {
|
||||
|
||||
if (!player.canCast()) {
|
||||
return null;
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
int maxDistance = player.asEntity().isCreative() ? 1000 : 100;
|
||||
|
@ -121,7 +117,7 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
|||
}
|
||||
|
||||
return new Pos(pos);
|
||||
}).orElse(null);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -130,20 +126,20 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void apply(Pony iplayer, Pos data) {
|
||||
teleport(iplayer, iplayer, data);
|
||||
public boolean apply(Pony iplayer, Pos data) {
|
||||
return teleport(iplayer, iplayer, data);
|
||||
}
|
||||
|
||||
protected void teleport(Pony teleporter, Caster<?> teleportee, Pos destination) {
|
||||
protected boolean teleport(Pony teleporter, Caster<?> teleportee, Pos destination) {
|
||||
|
||||
if (!teleporter.canCast()) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
Entity participant = teleportee.asEntity();
|
||||
|
||||
if (participant == null) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
teleportee.asWorld().playSound(null, teleportee.getOrigin(), USounds.ENTITY_PLAYER_UNICORN_TELEPORT, SoundCategory.PLAYERS, 1, 1);
|
||||
|
@ -177,6 +173,8 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
|||
participant.fallDistance /= distance;
|
||||
|
||||
participant.getWorld().playSound(null, destination.pos(), USounds.ENTITY_PLAYER_UNICORN_TELEPORT, SoundCategory.PLAYERS, 1, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean enterable(World w, BlockPos pos) {
|
||||
|
@ -200,13 +198,13 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void preApply(Pony player, AbilitySlot slot) {
|
||||
public void warmUp(Pony player, AbilitySlot slot) {
|
||||
player.getMagicalReserves().getExertion().add(30);
|
||||
player.spawnParticles(MagicParticleEffect.UNICORN, 5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postApply(Pony player, AbilitySlot slot) {
|
||||
public void coolDown(Pony player, AbilitySlot slot) {
|
||||
player.spawnParticles(MagicParticleEffect.UNICORN, 5);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,18 @@
|
|||
package com.minelittlepony.unicopia.ability.data;
|
||||
|
||||
import java.util.Optional;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
|
||||
public class Hit {
|
||||
public interface Hit {
|
||||
Optional<Hit> INSTANCE = Optional.of(new Hit() {});
|
||||
Serializer<Hit> SERIALIZER = new Serializer<>(buf -> INSTANCE.get(), (buf, t) -> {});
|
||||
|
||||
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;
|
||||
static Optional<Hit> of(boolean value) {
|
||||
return value ? INSTANCE : Optional.empty();
|
||||
}
|
||||
|
||||
protected Hit() {
|
||||
|
||||
}
|
||||
|
||||
public void toBuffer(PacketByteBuf buf) {
|
||||
|
||||
}
|
||||
|
||||
public interface Serializer<T extends Hit> {
|
||||
T fromBuffer(PacketByteBuf buf);
|
||||
public record Serializer<T extends Hit> (
|
||||
PacketByteBuf.PacketReader<T> read,
|
||||
PacketByteBuf.PacketWriter<T> write) {
|
||||
}
|
||||
}
|
|
@ -1,26 +1,16 @@
|
|||
package com.minelittlepony.unicopia.ability.data;
|
||||
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
|
||||
public class Multi extends Pos {
|
||||
public static final Serializer<Multi> SERIALIZER = Multi::new;
|
||||
|
||||
public final int hitType;
|
||||
|
||||
Multi(PacketByteBuf buf) {
|
||||
super(buf);
|
||||
hitType = buf.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBuffer(PacketByteBuf buf) {
|
||||
super.toBuffer(buf);
|
||||
buf.writeInt(hitType);
|
||||
}
|
||||
public record Multi (Pos pos, int hitType) implements Hit {
|
||||
public static final Serializer<Multi> SERIALIZER = new Serializer<>(
|
||||
buf -> new Multi(Pos.SERIALIZER.read().apply(buf), buf.readInt()),
|
||||
(buf, t) -> {
|
||||
Pos.SERIALIZER.write().accept(buf, t.pos());
|
||||
buf.writeInt(t.hitType());
|
||||
});
|
||||
|
||||
public Multi(Vec3i pos, int hit) {
|
||||
super(pos.getX(), pos.getY(), pos.getZ());
|
||||
hitType = hit;
|
||||
this(new Pos(pos), hit);
|
||||
}
|
||||
}
|
|
@ -1,22 +1,13 @@
|
|||
package com.minelittlepony.unicopia.ability.data;
|
||||
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import java.util.Optional;
|
||||
|
||||
public class Numeric extends Hit {
|
||||
public static final Serializer<Numeric> SERIALIZER = Numeric::new;
|
||||
public record Numeric (int type) implements Hit {
|
||||
public static final Serializer<Numeric> SERIALIZER = new Serializer<>(
|
||||
buf -> new Numeric(buf.readInt()),
|
||||
(buf, t) -> buf.writeInt(t.type()));
|
||||
|
||||
public int type;
|
||||
|
||||
Numeric(PacketByteBuf buf) {
|
||||
type = buf.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBuffer(PacketByteBuf buf) {
|
||||
buf.writeInt(type);
|
||||
}
|
||||
|
||||
public Numeric(int t) {
|
||||
type = t;
|
||||
public static Optional<Numeric> of(int type) {
|
||||
return Optional.of(new Numeric(type));
|
||||
}
|
||||
}
|
|
@ -2,40 +2,19 @@ package com.minelittlepony.unicopia.ability.data;
|
|||
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.util.math.*;
|
||||
|
||||
public class Pos extends Hit {
|
||||
public record Pos (int x, int y, int z) implements Hit {
|
||||
public static final Serializer<Pos> SERIALIZER = new Serializer<>(
|
||||
buf -> new Pos(buf.readInt(), buf.readInt(), buf.readInt()),
|
||||
(buf, t) -> {
|
||||
buf.writeInt(t.x());
|
||||
buf.writeInt(t.y());
|
||||
buf.writeInt(t.z());
|
||||
});
|
||||
|
||||
public static final Serializer<Pos> SERIALIZER = Pos::new;
|
||||
|
||||
public final int x;
|
||||
public final int y;
|
||||
public final int z;
|
||||
|
||||
Pos(PacketByteBuf buf) {
|
||||
x = buf.readInt();
|
||||
y = buf.readInt();
|
||||
z = buf.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBuffer(PacketByteBuf buf) {
|
||||
buf.writeInt(x);
|
||||
buf.writeInt(y);
|
||||
buf.writeInt(z);
|
||||
}
|
||||
|
||||
public Pos(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public Pos(BlockPos pos) {
|
||||
x = pos.getX();
|
||||
y = pos.getY();
|
||||
z = pos.getZ();
|
||||
public Pos(Vec3i pos) {
|
||||
this(pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
public BlockPos pos() {
|
||||
|
|
|
@ -26,7 +26,7 @@ public record MsgPlayerAbility<T extends Hit> (
|
|||
Ability<T> power = (Ability<T>) Abilities.REGISTRY.get(buffer.readIdentifier());
|
||||
return new MsgPlayerAbility<>(
|
||||
power,
|
||||
buffer.readOptional(power.getSerializer()::fromBuffer),
|
||||
buffer.readOptional(power.getSerializer().read()),
|
||||
ActivationType.of(buffer.readInt())
|
||||
);
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ public record MsgPlayerAbility<T extends Hit> (
|
|||
@Override
|
||||
public void toBuffer(PacketByteBuf buffer) {
|
||||
buffer.writeIdentifier(Abilities.REGISTRY.getId(power));
|
||||
buffer.writeOptional(data, (buf, t) -> t.toBuffer(buf));
|
||||
buffer.writeOptional(data, power.getSerializer().write());
|
||||
buffer.writeInt(type.ordinal());
|
||||
}
|
||||
|
||||
|
@ -48,10 +48,9 @@ public record MsgPlayerAbility<T extends Hit> (
|
|||
if (type != ActivationType.NONE) {
|
||||
power.onQuickAction(player, type, data);
|
||||
} else {
|
||||
data.filter(data -> power.canApply(player, data)).ifPresentOrElse(
|
||||
data -> power.apply(player, data),
|
||||
() -> Channel.CANCEL_PLAYER_ABILITY.sendToPlayer(new MsgCancelPlayerAbility(), sender)
|
||||
);
|
||||
if (data.filter(data -> power.apply(player, data)).isEmpty()) {
|
||||
Channel.CANCEL_PLAYER_ABILITY.sendToPlayer(new MsgCancelPlayerAbility(), sender);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue