From 8aa0885112c6b107b67b6b40e7057cfb94f019f9 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sun, 11 Oct 2020 13:14:41 +0200 Subject: [PATCH] Split kicking and stomping into separate abilities --- .../unicopia/ability/Abilities.java | 1 + .../ability/EarthPonyKickAbility.java | 190 ++++++++++++++++++ .../ability/EarthPonyStompAbility.java | 170 ++++------------ .../resources/assets/unicopia/lang/en_us.json | 1 + .../unicopia/textures/gui/ability/kick.png | Bin 0 -> 2069 bytes 5 files changed, 228 insertions(+), 134 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java create mode 100644 src/main/resources/assets/unicopia/textures/gui/ability/kick.png diff --git a/src/main/java/com/minelittlepony/unicopia/ability/Abilities.java b/src/main/java/com/minelittlepony/unicopia/ability/Abilities.java index 6be7cd9f..b8a1ebaa 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/Abilities.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/Abilities.java @@ -20,6 +20,7 @@ public interface Abilities { Ability SHOOT = register(new UnicornProjectileAbility(), "shoot", AbilitySlot.TERTIARY); // earth / alicorn + Ability KICK = register(new EarthPonyKickAbility(), "kick", AbilitySlot.PRIMARY); Ability GROW = register(new EarthPonyGrowAbility(), "grow", AbilitySlot.SECONDARY); Ability STOMP = register(new EarthPonyStompAbility(), "stomp", AbilitySlot.TERTIARY); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java new file mode 100644 index 00000000..77f9cfa8 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java @@ -0,0 +1,190 @@ +package com.minelittlepony.unicopia.ability; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import javax.annotation.Nullable; + +import com.google.common.collect.Lists; +import com.minelittlepony.unicopia.Race; +import com.minelittlepony.unicopia.TreeTraverser; +import com.minelittlepony.unicopia.TreeType; +import com.minelittlepony.unicopia.ability.data.Hit; +import com.minelittlepony.unicopia.ability.data.Pos; +import com.minelittlepony.unicopia.entity.player.Pony; +import com.minelittlepony.unicopia.util.PosHelper; +import com.minelittlepony.unicopia.util.RayTraceHelper; +import com.minelittlepony.unicopia.util.WorldEvent; +import com.minelittlepony.unicopia.util.shape.Shape; +import com.minelittlepony.unicopia.util.shape.Sphere; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.LeavesBlock; +import net.minecraft.entity.ItemEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.particle.BlockStateParticleEffect; +import net.minecraft.particle.ParticleTypes; +import net.minecraft.tag.BlockTags; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +/** + * Earth Pony kicking ability + */ +public class EarthPonyKickAbility implements Ability { + + @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) { + Optional p = RayTraceHelper.doTrace(player.getMaster(), 6, 1).getBlockPos(); + + if (p.isPresent()) { + BlockPos pos = p.get(); + BlockState state = player.getWorld().getBlockState(pos); + + if (state.getBlock().isIn(BlockTags.LOGS)) { + pos = TreeTraverser.Descender.descendTree(player.getWorld(), state, pos).get(); + if (TreeTraverser.Measurer.measureTree(player.getWorld(), state, pos) > 0) { + return new Pos(pos); + } + } + } + + return null; + } + + @Override + public Hit.Serializer 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; + } + + if (harmed || player.world.random.nextInt(5) == 0) { + + if (!harmed || player.world.random.nextInt(30) == 0) { + TreeTraverser.Remover.removeTree(player.world, data.pos()); + } + + iplayer.subtractEnergyCost(3); + } else { + int cost = dropApples(player.world, data.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 + ); + } + } + } + + private int dropApples(World w, BlockPos pos) { + BlockState log = w.getBlockState(pos); + int size = TreeTraverser.Measurer.measureTree(w, log, pos); + if (size > 0) { + + List capturedDrops = Lists.newArrayList(); + + dropApplesPart(capturedDrops, new ArrayList(), w, log, pos, 0); + + capturedDrops.forEach(item -> { + item.setToDefaultPickupDelay(); + w.spawnEntity(item); + }); + + return capturedDrops.size() / 3; + } + + return 0; + } + + private static void dropApplesPart(List drops, List done, World w, BlockState log, BlockPos pos, int level) { + if (!done.contains(pos)) { + done.add(pos); + pos = TreeTraverser.Ascender.ascendTree(w, log, pos, false); + if (level < 10 && TreeTraverser.isWoodOrLeaf(w, log, pos)) { + BlockState state = w.getBlockState(pos); + + if (state.getBlock() instanceof LeavesBlock && w.getBlockState(pos.down()).isAir()) { + WorldEvent.play(WorldEvent.DESTROY_BLOCK, w, pos, state); + drops.add(new ItemEntity(w, + pos.getX() + w.random.nextFloat(), + pos.getY() - 0.5, + pos.getZ() + w.random.nextFloat(), + TreeType.get(log).pickRandomStack() + )); + } + + PosHelper.all(pos, p -> { + dropApplesPart(drops, done, w, log, p, level + 1); + }, Direction.UP, Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST); + } + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java index 52495dff..7db679f3 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java @@ -1,21 +1,11 @@ package com.minelittlepony.unicopia.ability; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - import javax.annotation.Nullable; -import com.google.common.collect.Lists; import com.minelittlepony.unicopia.Race; -import com.minelittlepony.unicopia.TreeTraverser; -import com.minelittlepony.unicopia.TreeType; import com.minelittlepony.unicopia.ability.data.Hit; -import com.minelittlepony.unicopia.ability.data.Multi; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.util.MagicalDamageSource; -import com.minelittlepony.unicopia.util.PosHelper; -import com.minelittlepony.unicopia.util.RayTraceHelper; import com.minelittlepony.unicopia.util.WorldEvent; import com.minelittlepony.unicopia.util.shape.Shape; import com.minelittlepony.unicopia.util.shape.Sphere; @@ -23,26 +13,22 @@ import com.minelittlepony.unicopia.util.shape.Sphere; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; -import net.minecraft.block.LeavesBlock; import net.minecraft.block.ShapeContext; -import net.minecraft.entity.ItemEntity; import net.minecraft.entity.attribute.EntityAttributes; import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.particle.BlockStateParticleEffect; import net.minecraft.particle.ParticleTypes; -import net.minecraft.tag.BlockTags; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; -import net.minecraft.util.math.Vec3i; import net.minecraft.world.World; /** * Earth Pony stomping ability */ -public class EarthPonyStompAbility implements Ability { +public class EarthPonyStompAbility implements Ability { private final double rad = 4; @@ -73,109 +59,69 @@ public class EarthPonyStompAbility implements Ability { @Nullable @Override - public Multi tryActivate(Pony player) { - Optional p = RayTraceHelper.doTrace(player.getMaster(), 6, 1).getBlockPos(); - - if (p.isPresent()) { - BlockPos pos = p.get(); - BlockState state = player.getWorld().getBlockState(pos); - - if (state.getBlock().isIn(BlockTags.LOGS)) { - pos = TreeTraverser.Descender.descendTree(player.getWorld(), state, pos).get(); - if (TreeTraverser.Measurer.measureTree(player.getWorld(), state, pos) > 0) { - return new Multi(pos, 1); - } - } - } - + public Hit tryActivate(Pony player) { if (!player.getMaster().isOnGround() && !player.getMaster().abilities.flying) { player.getMaster().addVelocity(0, -6, 0); - return new Multi(Vec3i.ZERO, 0); + return Hit.INSTANCE; } return null; } @Override - public Hit.Serializer getSerializer() { - return Multi.SERIALIZER; + public Hit.Serializer getSerializer() { + return Hit.SERIALIZER; } - @Override - public void apply(Pony iplayer, Multi data) { + public void apply(Pony iplayer, Hit data) { PlayerEntity player = iplayer.getMaster(); - if (data.hitType == 0) { - BlockPos ppos = player.getBlockPos(); - BlockPos pos = getSolidBlockBelow(ppos, player.getEntityWorld()); + BlockPos ppos = player.getBlockPos(); + BlockPos pos = getSolidBlockBelow(ppos, player.getEntityWorld()); - player.addVelocity(0, -(ppos.getSquaredDistance(pos)), 0); + player.addVelocity(0, -(ppos.getSquaredDistance(pos)), 0); - iplayer.getWorld().getOtherEntities(player, areaOfEffect.offset(iplayer.getOriginVector())).forEach(i -> { - double dist = Math.sqrt(pos.getSquaredDistance(i.getBlockPos())); + iplayer.getWorld().getOtherEntities(player, areaOfEffect.offset(iplayer.getOriginVector())).forEach(i -> { + double dist = Math.sqrt(pos.getSquaredDistance(i.getBlockPos())); - if (dist <= rad + 3) { - double force = dist / 5; - i.addVelocity( - -(player.getX() - i.getX()) / force, - -(player.getY() - i.getY() - 2) / force + (dist < 1 ? dist : 0), - -(player.getZ() - i.getZ()) / force); + if (dist <= rad + 3) { + double force = dist / 5; + i.addVelocity( + -(player.getX() - i.getX()) / force, + -(player.getY() - i.getY() - 2) / force + (dist < 1 ? dist : 0), + -(player.getZ() - i.getZ()) / force); - DamageSource damage = MagicalDamageSource.create("smash", player); + DamageSource damage = MagicalDamageSource.create("smash", player); - double amount = (4 * player.getAttributeInstance(EntityAttributes.GENERIC_ATTACK_DAMAGE).getValue()) / (float)dist; + double amount = (4 * player.getAttributeInstance(EntityAttributes.GENERIC_ATTACK_DAMAGE).getValue()) / (float)dist; - if (i instanceof PlayerEntity) { - Race race = Pony.of((PlayerEntity)i).getSpecies(); - if (race.canUseEarth()) { - amount /= 3; - } - - if (race.canFly()) { - amount *= 4; - } + if (i instanceof PlayerEntity) { + Race race = Pony.of((PlayerEntity)i).getSpecies(); + if (race.canUseEarth()) { + amount /= 3; } - i.damage(damage, (float)amount); + if (race.canFly()) { + amount *= 4; + } } - }); - BlockPos.iterate(pos.add(-rad, -rad, -rad), pos.add(rad, rad, rad)).forEach(i -> { - if (i.getSquaredDistance(player.getX(), player.getY(), player.getZ(), true) <= rad*rad) { - spawnEffect(player.world, i); - } - }); - - for (int i = 1; i < 202; i+= 2) { - spawnParticleRing(player, i, 0); + i.damage(damage, (float)amount); } + }); - iplayer.subtractEnergyCost(rad); - } else if (data.hitType == 1) { - - boolean harmed = player.getHealth() < player.getMaxHealth(); - - if (harmed && player.world.random.nextInt(30) == 0) { - iplayer.subtractEnergyCost(3); - return; + BlockPos.iterate(pos.add(-rad, -rad, -rad), pos.add(rad, rad, rad)).forEach(i -> { + if (i.getSquaredDistance(player.getX(), player.getY(), player.getZ(), true) <= rad*rad) { + spawnEffect(player.world, i); } + }); - if (harmed || player.world.random.nextInt(5) == 0) { - - if (!harmed || player.world.random.nextInt(30) == 0) { - TreeTraverser.Remover.removeTree(player.world, data.pos()); - } - - iplayer.subtractEnergyCost(3); - } else { - int cost = dropApples(player.world, data.pos()); - - if (cost > 0) { - iplayer.subtractEnergyCost(cost * 3); - } - } + for (int i = 1; i < 202; i+= 2) { + spawnParticleRing(player, i, 0); } + + iplayer.subtractEnergyCost(rad); } private void spawnEffect(World w, BlockPos pos) { @@ -221,50 +167,6 @@ public class EarthPonyStompAbility implements Ability { } } - private int dropApples(World w, BlockPos pos) { - BlockState log = w.getBlockState(pos); - int size = TreeTraverser.Measurer.measureTree(w, log, pos); - if (size > 0) { - - List capturedDrops = Lists.newArrayList(); - - dropApplesPart(capturedDrops, new ArrayList(), w, log, pos, 0); - - capturedDrops.forEach(item -> { - item.setToDefaultPickupDelay(); - w.spawnEntity(item); - }); - - return capturedDrops.size() / 3; - } - - return 0; - } - - private static void dropApplesPart(List drops, List done, World w, BlockState log, BlockPos pos, int level) { - if (!done.contains(pos)) { - done.add(pos); - pos = TreeTraverser.Ascender.ascendTree(w, log, pos, false); - if (level < 10 && TreeTraverser.isWoodOrLeaf(w, log, pos)) { - BlockState state = w.getBlockState(pos); - - if (state.getBlock() instanceof LeavesBlock && w.getBlockState(pos.down()).isAir()) { - WorldEvent.play(WorldEvent.DESTROY_BLOCK, w, pos, state); - drops.add(new ItemEntity(w, - pos.getX() + w.random.nextFloat(), - pos.getY() - 0.5, - pos.getZ() + w.random.nextFloat(), - TreeType.get(log).pickRandomStack() - )); - } - - PosHelper.all(pos, p -> { - dropApplesPart(drops, done, w, log, p, level + 1); - }, Direction.UP, Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST); - } - } - } - private static BlockPos getSolidBlockBelow(BlockPos pos, World w) { while (!World.isHeightInvalid(pos)) { pos = pos.down(); diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index 4e83dd5f..676a9ba4 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -130,6 +130,7 @@ "ability.unicopia.teleport": "Teleport", "ability.unicopia.grow": "Earthly Nourishment", "ability.unicopia.stomp": "Ground Pound", + "ability.unicopia.kick": "Crushing Blow", "ability.unicopia.pummel": "Crushing Blow", "ability.unicopia.carry": "Pickup/Drop Passenger", "ability.unicopia.hang": "Cling to Ceiling", diff --git a/src/main/resources/assets/unicopia/textures/gui/ability/kick.png b/src/main/resources/assets/unicopia/textures/gui/ability/kick.png new file mode 100644 index 0000000000000000000000000000000000000000..de75f52f94742e2e03055a1f4778538b28d53c63 GIT binary patch literal 2069 zcmV+w2t2&N+KpKHS?DWhf>*x?Wat&ffX`^WW>N zy^in>;{LBTjMt8^L+0T{IQP~W?^ej$y}WNrpqVDtt_?&CQU@M<-gDyNkq_Tk-W37v z%^vQ!Y{EaEO{~p@=BSoB9VoG7GHEzvgRpH^19SkW>VNFL`s_8RCZ2gdAtrOo;Vm&& zEP}C?Sd}1!A;XP#512O-aN>1S#5Pp%^x076$M|NT^n$CNFWoj%T_uYMLkE|Ca)F_P z7?s>BqLontdlm<*7_f$zBjcc0QOv4v^H$cV6-FY+G-A3Q@nbrpkY?O@{#b_Y;M&ka z8Pb7ltl&p5>tRp`-r@v;56qT?OhenaLkP$N$rikVGXWP0AG-cEj^8@)*&ppCvznal5*Le5lI(X7-`-(G;RN-LF3-(Ax8UAj+GitM~<4hl&1 z3?1x0hS08v*q^ulI;ttkBtSs9@>d<9g;)e{l)*$a@b&_tI=b5M;AKY$1x~)A*OD!d zTrr0+2Vwn8nU=)XPtPAPFSO9QLRa9H`;^eamQS?Ij|CB!6GKji5D9Zln!ZZ7XjcbHQUrL;Cl;_cx z5_p3l@yEw1nuU@p?>Vkz>n~<}^NcZJY?*bLo9^k~+JSR^IPm22in9sr3jLDcoMGD~ zjc6*Ar25#NqC=_r_^Z91x^cwQuMM2Kal}bS7|y*l>lr6FX1QX5aLFArzH#Q5#ctrK zJu`yTx9)@os!1zmt|iTsXa{7lSZlCWc=}%hr*0gRhm4yzc0SuFSh1yY{MM;HxHZV8 z4HMK%x#!_RXyN%+BHmYynGYCmf%w)A0N9aZwl`wZK$9!AfxbBX`_rnZ#g>WW z8zx|?id!i>s}}b4XmvqRtNsA2FNvL3jfKHe`~X=Q0B=0U9u=rMAXtXPp#_}#c0bCt5(Q>0jG4BP{3a=Y4yn$l@Kb&FF4eDN(Dvm%@msrJr!#wgeDV8E zh7s9%Jei_)wb4|n!Y%hKam_hvdFfT~&eG-8%jk{^$GYo9IR4m%53F~{#6VV@GmKot z3?5?~*0;E-SdA3t(PCC$CLic$LWOA9bj6|$z4G|(27ty3e$;aHZwBTTJTJaBqvn-8 z=Hz1lhh^Z2dCsRp9v9XXk!{8lFs+idnq9IKkuZIcXM=c+@X{ON@ ze)mYvpp}b0Y8X10;8@p=kX6yf^ocXIB~s~ZHvO47dA3sMKB%jp(Gos^E)7 z=otoZHsQxDv%Q9i6&`w4P%$_Lu_Mp+=PG}AGVz1^qn_PC?qFmfT2HsQ%xGOe@RXFm zIYMLTX9YF;N3v-qh^2UFQ;(|!ROx%6G?pDN1s-}Lvumkg`*Yx$B9FXM zq%=4k*#5GL5y!PZe~l~8TE`S+d0!@#!g1>-T(fzEk;-?zc(`o2bI?E`1BS|wWOaD8 zq?~A+#n;N-TrsOf=)Q3KvH)EAsX59tlXPWb^$x5P)Cn~eE<0;NDTd{)=jg-6q+AF^ z>2L^zAs&P|F^CsNjbs1#u4>U7Syqd&Lh1jj6`NR452gry0vc2Vk>)VBUH5EoZLZ+>(pXI73#4FBuh!v3lr#!~Z3=e7wP#hFl}g zG%NQ>(@IOO|Hr=puX9AHZSbQf00000NkvXXu0mjf!iD0; literal 0 HcmV?d00001