Unicopia/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java

224 lines
7.7 KiB
Java
Raw Normal View History

package com.minelittlepony.unicopia.ability;
import java.util.List;
2021-08-04 15:38:03 +02:00
import org.jetbrains.annotations.Nullable;
import com.google.common.collect.Lists;
import com.minelittlepony.unicopia.BlockDestructionManager;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.ability.data.Pos;
2021-08-20 22:25:46 +02:00
import com.minelittlepony.unicopia.ability.data.tree.TreeType;
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.util.PosHelper;
import com.minelittlepony.unicopia.util.RayTraceHelper;
import com.minelittlepony.unicopia.util.shape.Shape;
import com.minelittlepony.unicopia.util.shape.Sphere;
import net.minecraft.block.BeehiveBlock;
2021-02-13 12:50:24 +01:00
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BeehiveBlockEntity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.passive.BeeEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.particle.BlockStateParticleEffect;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.WorldEvents;
/**
* Earth Pony kicking ability
*/
public class EarthPonyKickAbility implements Ability<Pos> {
@Override
public int getWarmupTime(Pony player) {
return 3;
}
@Override
public int getCooldownTime(Pony player) {
return 50;
}
@Override
public boolean canUse(Race race) {
return race.canUseEarth();
}
@Override
public double getCostEstimate(Pony player) {
return 3;
}
@Nullable
@Override
public Pos tryActivate(Pony player) {
2021-08-20 22:22:28 +02:00
return RayTraceHelper.doTrace(player.getMaster(), 6, 1).getBlockPos().map(Pos::new).orElse(null);
}
2021-08-20 22:22:28 +02:00
@Override
public boolean canApply(Pony player, Pos data) {
BlockPos pos = data.pos();
TreeType tree = TreeType.at(pos, player.getWorld());
2021-08-20 22:22:28 +02:00
return tree != TreeType.NONE && tree.findBase(player.getWorld(), pos).map(base -> {
return tree.countBlocks(player.getWorld(), pos) > 0;
}).orElse(false);
}
@Override
public Hit.Serializer<Pos> getSerializer() {
return Pos.SERIALIZER;
}
@Override
public void apply(Pony iplayer, Pos data) {
PlayerEntity player = iplayer.getMaster();
boolean harmed = player.getHealth() < player.getMaxHealth();
if (harmed && player.world.random.nextInt(30) == 0) {
iplayer.subtractEnergyCost(3);
return;
}
iplayer.setAnimation(Animation.KICK, 30);
BlockPos pos = data.pos();
BlockDestructionManager destr = ((BlockDestructionManager.Source)player.world).getDestructionManager();
if (destr.getBlockDestruction(pos) + 4 >= BlockDestructionManager.MAX_DAMAGE) {
if (!harmed || player.world.random.nextInt(30) == 0) {
TreeType.at(pos, player.world).traverse(player.world, pos, (w, state, p, recurseLevel) -> {
2021-02-13 12:50:24 +01:00
if (recurseLevel < 5) {
w.breakBlock(p, true);
} else {
Block.dropStacks(w.getBlockState(p), w, p);
w.setBlockState(p, Blocks.AIR.getDefaultState(), 3);
}
});
}
iplayer.subtractEnergyCost(3);
} else {
2021-02-13 12:50:24 +01:00
int cost = dropApples(player, pos);
if (cost > 0) {
iplayer.subtractEnergyCost(cost * 3);
}
}
}
@Override
public void preApply(Pony player, AbilitySlot slot) {
player.getMagicalReserves().getExertion().add(40);
}
@Override
public void postApply(Pony player, AbilitySlot slot) {
int timeDiff = getCooldownTime(player) - player.getAbilities().getStat(slot).getRemainingCooldown();
if (player.getMaster().getEntityWorld().getTime() % 1 == 0 || timeDiff == 0) {
spawnParticleRing(player.getMaster(), timeDiff, 1);
}
}
private void spawnParticleRing(PlayerEntity player, int timeDiff, double yVel) {
int animationTicks = timeDiff / 10;
if (animationTicks < 6) {
Shape shape = new Sphere(true, animationTicks, 1, 0, 1);
double y = 0.5 + (Math.sin(animationTicks) * 1.5);
yVel *= y * 5;
for (int i = 0; i < shape.getVolumeOfSpawnableSpace(); i++) {
Vec3d point = shape.computePoint(player.getEntityWorld().random).add(player.getPos());
player.world.addParticle(new BlockStateParticleEffect(ParticleTypes.BLOCK, Blocks.DIRT.getDefaultState()),
point.x,
point.y + y,
point.z,
0, yVel, 0
);
}
}
}
2021-02-13 12:50:24 +01:00
private int dropApples(PlayerEntity player, BlockPos pos) {
TreeType tree = TreeType.at(pos, player.world);
2021-02-13 12:50:24 +01:00
if (tree.countBlocks(player.world, pos) > 0) {
List<ItemEntity> capturedDrops = Lists.newArrayList();
2021-02-13 12:50:24 +01:00
tree.traverse(player.world, pos, (world, state, position, recurse) -> {
affectBlockChange(player, position);
}, (world, state, position, recurse) -> {
affectBlockChange(player, position);
if (world.getBlockState(position.down()).isAir()) {
ItemStack stack = tree.pickRandomStack(state);
if (!stack.isEmpty()) {
world.syncWorldEvent(WorldEvents.BLOCK_BROKEN, position, Block.getRawIdFromState(state));
capturedDrops.add(new ItemEntity(world,
2021-02-13 12:50:24 +01:00
position.getX() + world.random.nextFloat(),
position.getY() - 0.5,
position.getZ() + world.random.nextFloat(),
stack
2021-02-13 12:50:24 +01:00
));
}
2021-02-13 12:50:24 +01:00
}
});
capturedDrops.forEach(item -> {
item.setToDefaultPickupDelay();
2021-02-13 12:50:24 +01:00
player.world.spawnEntity(item);
});
return capturedDrops.size() / 3;
}
return 0;
}
2021-02-13 12:50:24 +01:00
private void affectBlockChange(PlayerEntity player, BlockPos position) {
BlockDestructionManager destr = ((BlockDestructionManager.Source)player.world).getDestructionManager();
destr.damageBlock(position, 4);
PosHelper.all(position, p -> {
BlockState s = player.world.getBlockState(p);
if (s.getBlock() instanceof BeehiveBlock) {
BeehiveBlockEntity hive = (BeehiveBlockEntity)player.world.getBlockEntity(p);
if (hive != null) {
hive.angerBees(player, s, BeehiveBlockEntity.BeeState.BEE_RELEASED);
}
Box area = new Box(position).expand(8, 6, 8);
List<BeeEntity> nearbyBees = player.world.getNonSpectatingEntities(BeeEntity.class, area);
if (!nearbyBees.isEmpty()) {
List<PlayerEntity> nearbyPlayers = player.world.getNonSpectatingEntities(PlayerEntity.class, area);
int i = nearbyPlayers.size();
for (BeeEntity bee : nearbyBees) {
if (bee.getTarget() == null) {
bee.setTarget(nearbyPlayers.get(player.world.random.nextInt(i)));
}
}
}
}
}, PosHelper.HORIZONTAL);
}
}