diff --git a/src/main/java/com/floralquafloral/bumping/BumpManager.java b/src/main/java/com/floralquafloral/bumping/BumpManager.java index d521eab..d88fb02 100644 --- a/src/main/java/com/floralquafloral/bumping/BumpManager.java +++ b/src/main/java/com/floralquafloral/bumping/BumpManager.java @@ -7,7 +7,6 @@ import com.floralquafloral.mariodata.MarioClientSideData; import com.floralquafloral.mariodata.MarioData; import com.floralquafloral.mariodata.MarioDataManager; -import com.floralquafloral.mariodata.MarioDataPackets; import com.floralquafloral.mariodata.moveable.MarioMainClientData; import com.floralquafloral.mariodata.moveable.MarioServerData; import com.floralquafloral.mariodata.moveable.MarioTravelData; @@ -24,11 +23,13 @@ import net.minecraft.block.BlockState; import net.minecraft.client.MinecraftClient; import net.minecraft.client.world.ClientWorld; -import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.RegistryByteBuf; import net.minecraft.network.codec.PacketCodec; import net.minecraft.network.codec.PacketCodecs; import net.minecraft.network.packet.CustomPayload; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.tag.TagKey; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.BlockSoundGroup; import net.minecraft.sound.SoundCategory; @@ -45,11 +46,16 @@ import java.util.*; +import static com.floralquafloral.MarioQuaMario.MOD_ID; + public abstract class BumpManager { public static final Map BUMPED_BLOCKS = new HashMap<>(); public static final Set HIDDEN_BLOCKS = new HashSet<>(); private static final Set BLOCKS_TO_BUMP = new HashSet<>(); + public static final TagKey ALWAYS_REPEAT_BUMP = TagKey.of(RegistryKeys.BLOCK, Identifier.of(MOD_ID, "always_repeat_bump")); + public static final TagKey NEVER_REPEAT_BUMP = TagKey.of(RegistryKeys.BLOCK, Identifier.of(MOD_ID, "never_repeat_bump")); + private record BlockBumpingPlan(ClientWorld world, BlockPos pos, BlockState state, Direction direction) {} public static void registerPackets() { @@ -57,9 +63,11 @@ public static void registerPackets() { BumpC2SPayload.registerReceiver(); BumpS2CPayload.register(); + AllowRepeatBumpS2CPayload.register(); } public static void registerPacketsClient() { BumpS2CPayload.registerReceiver(); + AllowRepeatBumpS2CPayload.registerReceiver(); } private static BlockPos eyeAdjustmentParticlePos; @@ -79,7 +87,6 @@ public static void registerEventListeners() { if(!BLOCKS_TO_BUMP.isEmpty()) { for(BlockBumpingPlan plan : BLOCKS_TO_BUMP) { visuallyBumpBlock(plan.world, plan.pos, plan.direction); - MarioQuaMario.LOGGER.info("Pos1: {}, Pos2: {}, Equal: {}", plan.pos, eyeAdjustmentParticlePos, plan.pos.equals(eyeAdjustmentParticlePos)); if(plan.pos.equals(eyeAdjustmentParticlePos)) { eyeAdjustmentParticle = BUMPED_BLOCKS.get(plan.pos); } @@ -137,6 +144,7 @@ public static void bumpBlocks(MarioMainClientData data, ClientWorld world, Itera int modifiedStrength = baseStrength + data.getPowerUp().BUMP_STRENGTH_MODIFIER + data.getCharacter().BUMP_STRENGTH_MODIFIER; Set blockSoundGroups = new HashSet<>(); BlockPos lastPos = null; + data.getTimers().canRepeatPound = false; for(BlockPos bumpPos : blocks) { bumpAttemptCount++; lastPos = new BlockPos(bumpPos); @@ -165,7 +173,6 @@ public static void bumpBlocks(MarioMainClientData data, ClientWorld world, Itera ); if(direction == Direction.DOWN && bumpCount == bumpAttemptCount) { - MarioQuaMario.LOGGER.info("Bumped down with full success! Setting EAPP to {}", lastPos); eyeAdjustmentParticlePos = lastPos; } } @@ -239,10 +246,19 @@ public static void bumpResponseCommon( BlockState state, BlockPos pos, int baseStrength, int modifiedStrength, Direction direction ) { - for(BumpingHandler handler : HANDLERS) { - if(handler.bumpResponseCommon(data, travelData, world, state, pos, baseStrength, modifiedStrength, direction)) return; + response: { + for(BumpingHandler handler : HANDLERS) { + if(handler.bumpResponseCommon(data, travelData, world, state, pos, baseStrength, modifiedStrength, direction)) + break response; + } + BASELINE_HANDLER.bumpResponseCommon(data, travelData, world, state, pos, baseStrength, modifiedStrength, direction); + } + if(!state.isIn(NEVER_REPEAT_BUMP) && (state.isIn(ALWAYS_REPEAT_BUMP) || !state.equals(world.getBlockState(pos)))) { + if(data.getMario() instanceof ServerPlayerEntity marioServer) + ServerPlayNetworking.send(marioServer, new AllowRepeatBumpS2CPayload()); + else if(data.getMario().isMainPlayer()) + ((MarioMainClientData) data).getTimers().canRepeatPound = true; // is this even possible?? } - BASELINE_HANDLER.bumpResponseCommon(data, travelData, world, state, pos, baseStrength, modifiedStrength, direction); } public static void bumpResponseClients( @@ -315,4 +331,22 @@ public static void register() { PayloadTypeRegistry.playS2C().register(ID, CODEC); } } + + private record AllowRepeatBumpS2CPayload() implements CustomPayload { + public static final CustomPayload.Id ID = new CustomPayload.Id<>(Identifier.of(MarioQuaMario.MOD_ID, "allow_repeat_bump")); + public static final PacketCodec CODEC = PacketCodec.unit(new AllowRepeatBumpS2CPayload()); + public static void registerReceiver() { + ClientPlayNetworking.registerGlobalReceiver(ID, (payload, context) -> { + MarioMainClientData data = MarioMainClientData.getInstance(); + if(data != null) data.getTimers().canRepeatPound = true; + }); + } + + @Override public Id getId() { + return ID; + } + public static void register() { + PayloadTypeRegistry.playS2C().register(ID, CODEC); + } + } } diff --git a/src/main/java/com/floralquafloral/bumping/handlers/BaselineBumpingHandler.java b/src/main/java/com/floralquafloral/bumping/handlers/BaselineBumpingHandler.java index 64e54d7..3aeb5cf 100644 --- a/src/main/java/com/floralquafloral/bumping/handlers/BaselineBumpingHandler.java +++ b/src/main/java/com/floralquafloral/bumping/handlers/BaselineBumpingHandler.java @@ -55,40 +55,61 @@ private ForcedSignalSpot(BlockPos position, World world) { public static final TagKey UNBREAKABLE_FROM_BUMPING = TagKey.of(RegistryKeys.BLOCK, Identifier.of(MOD_ID, "unbreakable_from_bumping")); // public static final TagKey BRICK_BLOCKS = TagKey.of(RegistryKeys.BLOCK, Identifier.of(MOD_ID, "brick_blocks")); + private float getAdjustedHardness(BlockState state, BlockView world, BlockPos pos, Direction direction) { + float adjustedHardness = state.getHardness(world, pos); + if(state.isTransparent(world, pos) && !state.hasSidedTransparency()) adjustedHardness *= 0.5F; + + return adjustedHardness; + } + @Override @NotNull public BumpLegality evaluateBumpLegality(BlockState state, BlockView world, BlockPos pos, int strength, Direction direction) { if(state.isIn(UNBUMPABLE)) return BumpLegality.IGNORE; if(state.isIn(BUMP_REGARDLESS_OF_HARDNESS) && strength >= 4) return BumpLegality.BUMP; if(state.isIn(EXTREMELY_EASY_TO_BUMP) && strength >= 1) return BumpLegality.BUMP; - float hardnessToolless = state.getHardness(world, pos); - if(state.isToolRequired()) hardnessToolless *= 3.33333333333F; - if(state.isTransparent(world, pos) && !state.hasSidedTransparency()) hardnessToolless *= 0.5F; - if(state.isIn(BlockTags.AXE_MINEABLE)) hardnessToolless *= 3.6F; - if(state.getBlock().toString().contains("brick")) hardnessToolless *= 0.5F; +// float hardnessToolless = state.getHardness(world, pos); +// if(state.isToolRequired()) hardnessToolless *= 3.33333333333F; +// if(state.isTransparent(world, pos) && !state.hasSidedTransparency()) hardnessToolless *= 0.5F; +// if(state.isIn(BlockTags.AXE_MINEABLE)) hardnessToolless *= 3.6F; +// if(state.getBlock().toString().contains("brick")) hardnessToolless *= 0.5F; - if(hardnessToolless == -1) return BumpLegality.IGNORE; + float adjustedHardness = getAdjustedHardness(state, world, pos, direction); + if(adjustedHardness == -1) return BumpLegality.IGNORE; if(strength <= 1) return BumpLegality.IGNORE; - if(strength == 2 && hardnessToolless <= 0.25F) return BumpLegality.SILENT_REACTION; - else if(hardnessToolless <= 2.5F * strength) return BumpLegality.BUMP; + if(strength == 2) return (adjustedHardness <= 0.25F) ? BumpLegality.SILENT_REACTION : BumpLegality.IGNORE; + if(adjustedHardness <= 0.75F * strength) return BumpLegality.BUMP; return BumpLegality.IGNORE; } @Override public boolean bumpResponseCommon(MarioData data, @Nullable MarioTravelData travelData, World world, BlockState state, BlockPos pos, int baseStrength, int modifiedStrength, Direction direction) { - float hardnessToolless = state.getHardness(world, pos); - if(state.isToolRequired()) hardnessToolless *= 3.33333333333F; - if(state.isTransparent(world, pos) && !state.hasSidedTransparency()) hardnessToolless *= 0.5F; - if(state.isIn(BlockTags.AXE_MINEABLE)) hardnessToolless *= 3.6F; - if(state.getBlock().toString().contains("brick")) hardnessToolless *= 0.5F; - - if(!state.isIn(UNBREAKABLE_FROM_BUMPING) && hardnessToolless != -1) { - if (modifiedStrength >= 4 && hardnessToolless <= 3.5 && world.breakBlock(pos, true, data.getMario())) - return true; - - if (modifiedStrength >= 2 && hardnessToolless <= 0.3 && world.breakBlock(pos, true, data.getMario())) + float adjustedHardness = getAdjustedHardness(state, world, pos, direction); + + attemptBreak: if(!state.isIn(UNBREAKABLE_FROM_BUMPING) && adjustedHardness != -1) { + if(modifiedStrength <= 1) break attemptBreak; + + // Super Mario spin-jumping can destroy fairly fragile blocks (ice, + if(modifiedStrength == 2) { + if(adjustedHardness <= 0.25F && world.breakBlock(pos, true, data.getMario())) + return true; + else break attemptBreak; + } +// if(!state.isToolRequired()) adjustedHardness -= 1; + + // Small Mario ground-pounding or bopping a ceiling can only break exceptionally fragile blocks (candles, moss, scaffolding) + if(modifiedStrength == 3) { + if(adjustedHardness < 0.2F && world.breakBlock(pos, true, data.getMario())) + return true; + else break attemptBreak; + } + + // Super Mario gets a bonus to breaking bricks + if(state.getBlock().toString().contains("brick")) adjustedHardness -= 1; + + if(adjustedHardness <= modifiedStrength * 0.25F && world.breakBlock(pos, true, data.getMario())) return true; } diff --git a/src/main/java/com/floralquafloral/bumping/handlers/PistonBumpingHandler.java b/src/main/java/com/floralquafloral/bumping/handlers/PistonBumpingHandler.java index 1f9cace..89ec46e 100644 --- a/src/main/java/com/floralquafloral/bumping/handlers/PistonBumpingHandler.java +++ b/src/main/java/com/floralquafloral/bumping/handlers/PistonBumpingHandler.java @@ -15,8 +15,6 @@ import org.jetbrains.annotations.Nullable; public class PistonBumpingHandler implements BumpingHandler { - public static boolean forceRetract; - @Override public @Nullable BumpLegality evaluateBumpLegality(BlockState state, BlockView world, BlockPos pos, int strength, Direction direction) { if(state.isOf(Blocks.PISTON_HEAD) && state.get(Properties.FACING) == Direction.UP) { diff --git a/src/main/java/com/floralquafloral/bumping/handlers/SpawnerBumpingHandler.java b/src/main/java/com/floralquafloral/bumping/handlers/SpawnerBumpingHandler.java new file mode 100644 index 0000000..3bab6e8 --- /dev/null +++ b/src/main/java/com/floralquafloral/bumping/handlers/SpawnerBumpingHandler.java @@ -0,0 +1,55 @@ +package com.floralquafloral.bumping.handlers; + +import com.floralquafloral.mariodata.MarioClientSideData; +import com.floralquafloral.mariodata.MarioData; +import com.floralquafloral.mariodata.moveable.MarioTravelData; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.SpawnerBlock; +import net.minecraft.block.TrialSpawnerBlock; +import net.minecraft.block.entity.MobSpawnerBlockEntity; +import net.minecraft.block.entity.TrialSpawnerBlockEntity; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.state.property.Properties; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.BlockView; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; + +public class SpawnerBumpingHandler implements BumpingHandler { + @Override + public @Nullable BumpLegality evaluateBumpLegality(BlockState state, BlockView world, BlockPos pos, int strength, Direction direction) { + if(state.isOf(Blocks.SPAWNER) || state.isOf(Blocks.TRIAL_SPAWNER)) { + return BumpLegality.BUMP; + } + return null; + } + + @Override + public boolean bumpResponseCommon(MarioData data, @Nullable MarioTravelData travelData, World world, BlockState state, BlockPos pos, int baseStrength, int modifiedStrength, Direction direction) { + if(world instanceof ServerWorld serverWorld) { + if(world.getBlockEntity(pos) instanceof MobSpawnerBlockEntity spawnerEntity) { + for(int incrementeroo = 0; incrementeroo < 7; incrementeroo++) { + spawnerEntity.getLogic().serverTick(serverWorld, pos); + } + return true; + } + + if(world.getBlockEntity(pos) instanceof TrialSpawnerBlockEntity trialSpawnerEntity) { + for(int incrementeroo = 0; incrementeroo < 3; incrementeroo++) { + trialSpawnerEntity.getSpawner().trySpawnMob(serverWorld, pos); + } + return true; + } + } + + return false; + } + + @Override + public boolean bumpResponseClients(MarioClientSideData data, ClientWorld world, BlockState state, BlockPos pos, int baseStrength, int modifiedStrength, Direction direction) { + return false; + } +} diff --git a/src/main/java/com/floralquafloral/bumping/handlers/TrapdoorBumpingHandler.java b/src/main/java/com/floralquafloral/bumping/handlers/TrapdoorBumpingHandler.java index 0854465..3c79208 100644 --- a/src/main/java/com/floralquafloral/bumping/handlers/TrapdoorBumpingHandler.java +++ b/src/main/java/com/floralquafloral/bumping/handlers/TrapdoorBumpingHandler.java @@ -18,7 +18,7 @@ public class TrapdoorBumpingHandler implements BumpingHandler { @Override public @Nullable BumpLegality evaluateBumpLegality(BlockState state, BlockView world, BlockPos pos, int strength, Direction direction) { - if(state.isIn(BlockTags.TRAPDOORS)) { + if(state.isIn(BlockTags.TRAPDOORS) && strength >= (state.isIn(BlockTags.WOODEN_TRAPDOORS) ? 3 : 4)) { if(state.get(Properties.OPEN)) { // It's an open trapdoor; check to see if we'd be knocking it closed if ( diff --git a/src/main/java/com/floralquafloral/mariodata/moveable/MarioMainClientData.java b/src/main/java/com/floralquafloral/mariodata/moveable/MarioMainClientData.java index 359b1ed..6ef983d 100644 --- a/src/main/java/com/floralquafloral/mariodata/moveable/MarioMainClientData.java +++ b/src/main/java/com/floralquafloral/mariodata/moveable/MarioMainClientData.java @@ -55,7 +55,7 @@ public MarioMainClientData(ClientPlayerEntity mario) { public final float[] CAMERA_ROTATIONS = new float[3]; @Override public void setActionTransitionless(ParsedAction action) { - MarioQuaMario.LOGGER.info("MarioMainClientData setAction to " + action.ID); +// MarioQuaMario.LOGGER.info("MarioMainClientData setAction to " + action.ID); if(action != getAction()) getTimers().actionTimer = 0; // CPM animation @@ -102,6 +102,9 @@ public MarioMainClientData(ClientPlayerEntity mario) { getAction().travelHook(this); getAction().attemptTransitions(this, TransitionPhase.POST_TICK); + getTimers().jumpLandingTime--; + getTimers().doubleJumpLandingTime--; + applyModifiedVelocity(); marioClient.move(MovementType.SELF, marioClient.getVelocity()); @@ -182,7 +185,7 @@ private static class ClientButton implements ButtonInput { } private boolean unbuffer() { - this.pressBuffer = 1; + this.pressBuffer = 0; return true; } diff --git a/src/main/java/com/floralquafloral/mariodata/moveable/MarioServerData.java b/src/main/java/com/floralquafloral/mariodata/moveable/MarioServerData.java index 9a5c8c3..9e60af3 100644 --- a/src/main/java/com/floralquafloral/mariodata/moveable/MarioServerData.java +++ b/src/main/java/com/floralquafloral/mariodata/moveable/MarioServerData.java @@ -34,7 +34,7 @@ public MarioServerData(ServerPlayerEntity mario) { @Override public void setActionTransitionless(ParsedAction action) { - MarioQuaMario.LOGGER.info("MarioServerData setAction to {}", action.ID); +// MarioQuaMario.LOGGER.info("MarioServerData setAction to {}", action.ID); if(this.getAction().ANIMATION != null) CPMIntegration.commonAPI.playAnimation(PlayerEntity.class, this.marioServer, this.getAction().ANIMATION, 0); diff --git a/src/main/java/com/floralquafloral/mariodata/moveable/MarioTravelData.java b/src/main/java/com/floralquafloral/mariodata/moveable/MarioTravelData.java index 68dba2b..6a4046a 100644 --- a/src/main/java/com/floralquafloral/mariodata/moveable/MarioTravelData.java +++ b/src/main/java/com/floralquafloral/mariodata/moveable/MarioTravelData.java @@ -56,5 +56,6 @@ class MarioTimers { public int doubleJumpLandingTime = 0; public boolean jumpCapped = false; + public boolean canRepeatPound = true; } } diff --git a/src/main/java/com/floralquafloral/registries/states/action/AirborneActionDefinition.java b/src/main/java/com/floralquafloral/registries/states/action/AirborneActionDefinition.java index 1278617..57ab48e 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/AirborneActionDefinition.java +++ b/src/main/java/com/floralquafloral/registries/states/action/AirborneActionDefinition.java @@ -54,7 +54,7 @@ public static ActionTransitionDefinition makeJumpCapTransition(ActionDefinition public static final ActionTransitionDefinition GROUND_POUND = new ActionTransitionDefinition( "qua_mario:ground_pound_windup", data -> data.getInputs().DUCK.isPressed(), - null, + data -> data.getMario().fallDistance *= 0.4F, (data, isSelf, seed) -> data.playSoundEvent(MarioSFX.GROUND_POUND_PRE, seed) ); } diff --git a/src/main/java/com/floralquafloral/registries/states/action/baseactions/GroundPound.java b/src/main/java/com/floralquafloral/registries/states/action/baseactions/GroundPound.java index 36450a3..93869f2 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/baseactions/GroundPound.java +++ b/src/main/java/com/floralquafloral/registries/states/action/baseactions/GroundPound.java @@ -39,7 +39,7 @@ public class GroundPound implements ActionDefinition { return SlidingStatus.NOT_SLIDING; } @Override public @Nullable Identifier getStompType() { - return Identifier.of("qua_mario", "stomp"); + return Identifier.of("qua_mario", "ground_pound"); } @Override public void travelHook(MarioTravelData data) { @@ -73,7 +73,7 @@ public class GroundPound implements ActionDefinition { new ActionTransitionDefinition( "qua_mario:ground_pound_landing", AirborneActionDefinition.AerialTransitions.BASIC_LANDING.EVALUATOR, - data -> {}, + data -> data.setForwardStrafeVel(0, 0), (data, isSelf, seed) -> data.playSoundEvent(MarioSFX.GROUND_POUND, seed) ) ); diff --git a/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/Backflip.java b/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/Backflip.java index 149dbd2..080f690 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/Backflip.java +++ b/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/Backflip.java @@ -56,15 +56,8 @@ else airborneAccel(data, @Override public List getPostTickTransitions() { return List.of( - AerialTransitions.makeJumpCapTransition(this, 0.765), - AerialTransitions.GROUND_POUND - ); - } - - @Override - public List getPostMoveTransitions() { - return List.of( - AerialTransitions.BASIC_LANDING + AerialTransitions.GROUND_POUND, + AerialTransitions.makeJumpCapTransition(this, 0.765) ); } } diff --git a/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/DoubleJump.java b/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/DoubleJump.java new file mode 100644 index 0000000..0b03fde --- /dev/null +++ b/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/DoubleJump.java @@ -0,0 +1,70 @@ +package com.floralquafloral.registries.states.action.baseactions.airborne; + +import com.floralquafloral.MarioQuaMario; +import com.floralquafloral.mariodata.MarioClientSideData; +import com.floralquafloral.mariodata.moveable.MarioTravelData; +import com.floralquafloral.registries.states.action.GroundedActionDefinition; +import com.floralquafloral.stats.CharaStat; +import com.floralquafloral.stats.StatCategory; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +import static com.floralquafloral.util.MixedEasing.*; + +public class DoubleJump extends Jump { + @Override public @NotNull Identifier getID() { + return Identifier.of(MarioQuaMario.MOD_ID, "double_jump"); + } + @Override public @Nullable String getAnimationName() { + return "double-jump"; + } + + public static CharaStat DOUBLE_JUMP_VEL = new CharaStat(0.939, StatCategory.JUMP_VELOCITY); + public static CharaStat DOUBLE_JUMP_VEL_ADDEND = new CharaStat(0.08, StatCategory.JUMP_VELOCITY); + public static CharaStat DOUBLE_JUMP_SPEED_THRESHOLD = new CharaStat(0, + StatCategory.WALKING, StatCategory.FORWARD, StatCategory.THRESHOLD); + + @Override public List getPostTickTransitions() { + return List.of( + AerialTransitions.GROUND_POUND, + AerialTransitions.makeJumpCapTransition(this, 0.285) + ); + } + + @Override + public List getPostMoveTransitions() { + return List.of( + AerialTransitions.TRIPLE_JUMPABLE_LANDING + ); + } + + private ActionTransitionInjection makeInjectionFrom(String otherAction) { + return new ActionTransitionInjection( + ActionTransitionInjection.InjectionPlacement.BEFORE, + otherAction, + ActionTransitionInjection.ActionCategory.GROUNDED, + new ActionTransitionDefinition("qua_mario:double_jump", + data -> + data.getTimers().jumpLandingTime > 0 + && data.getForwardVel() > DOUBLE_JUMP_SPEED_THRESHOLD.get(data) + && GroundedActionDefinition.GroundedTransitions.JUMP.EVALUATOR.shouldTransition(data), + data -> GroundedActionDefinition.GroundedTransitions.performJump(data, DOUBLE_JUMP_VEL, DOUBLE_JUMP_VEL_ADDEND), + (data, isSelf, seed) -> { + data.playJumpSound(seed); + data.voice(MarioClientSideData.VoiceLine.DOUBLE_JUMP, seed); + } + ) + ); + } + + @Override + public List getTransitionInjections() { + return List.of( + makeInjectionFrom("qua_mario:jump"), + makeInjectionFrom("qua_mario:p_jump") + ); + } +} diff --git a/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/TripleJump.java b/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/TripleJump.java new file mode 100644 index 0000000..023c785 --- /dev/null +++ b/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/TripleJump.java @@ -0,0 +1,79 @@ +package com.floralquafloral.registries.states.action.baseactions.airborne; + +import com.floralquafloral.MarioQuaMario; +import com.floralquafloral.mariodata.MarioClientSideData; +import com.floralquafloral.registries.states.action.GroundedActionDefinition; +import com.floralquafloral.stats.CharaStat; +import com.floralquafloral.stats.StatCategory; +import com.floralquafloral.util.Easings; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +import static com.floralquafloral.util.MixedEasing.*; + +public class TripleJump extends Jump { + @Override public @NotNull Identifier getID() { + return Identifier.of(MarioQuaMario.MOD_ID, "triple_jump"); + } + @Override public @Nullable String getAnimationName() { + return "triple-jump"; + } + @Override @Nullable public CameraAnimationSet getCameraAnimations() { + return new CameraAnimationSet( + new CameraAnimation( + false, 0.85F, + (progress, offsets) -> offsets[1] = Easings.easeOutQuad(progress) * 360 + ), + null, + null + ); + } + + public static CharaStat TRIPLE_JUMP_VEL = new CharaStat(1.175, StatCategory.JUMP_VELOCITY); + public static CharaStat TRIPLE_JUMP_SPEED_THRESHOLD = new CharaStat(0.34, + StatCategory.RUNNING, StatCategory.FORWARD, StatCategory.THRESHOLD); + + @Override public List getPostTickTransitions() { + return List.of( + AerialTransitions.GROUND_POUND, + AerialTransitions.makeJumpCapTransition(this, 0.65) + ); + } + + private ActionTransitionInjection makeInjectionFrom(String otherAction) { + return new ActionTransitionInjection( + ActionTransitionInjection.InjectionPlacement.BEFORE, + otherAction, + ActionTransitionInjection.ActionCategory.GROUNDED, + new ActionTransitionDefinition("qua_mario:triple_jump", + data -> + data.getTimers().doubleJumpLandingTime > 0 + && data.getForwardVel() > TRIPLE_JUMP_SPEED_THRESHOLD.get(data) + && GroundedActionDefinition.GroundedTransitions.JUMP.EVALUATOR.shouldTransition(data), + data -> GroundedActionDefinition.GroundedTransitions.performJump(data, TRIPLE_JUMP_VEL, null), + (data, isSelf, seed) -> { + data.playJumpSound(seed); + data.voice(MarioClientSideData.VoiceLine.TRIPLE_JUMP, seed); + } + ) + ); + } + + @Override + public List getPostMoveTransitions() { + return List.of( + AerialTransitions.BASIC_LANDING + ); + } + + @Override + public List getTransitionInjections() { + return List.of( + makeInjectionFrom("qua_mario:jump"), + makeInjectionFrom("qua_mario:p_jump") + ); + } +} diff --git a/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/GroundPoundLanding.java b/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/GroundPoundLanding.java index 2a0987f..8623edc 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/GroundPoundLanding.java +++ b/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/GroundPoundLanding.java @@ -51,8 +51,11 @@ public void groundedTravel(MarioTravelData data) { @Override public List getPreTickTransitions() { return List.of( + new ActionTransitionDefinition("qua_mario:ground_pound", + data -> data.getTimers().actionTimer > 3 && data.getInputs().DUCK.isHeld() && data.getTimers().canRepeatPound + ), new ActionTransitionDefinition("qua_mario:basic", - data -> (data.getTimers().actionTimer > 3 && !data.getInputs().DUCK.isHeld()) + data -> (data.getTimers().actionTimer > 4 && !data.getInputs().DUCK.isHeld()) ) ); } diff --git a/src/main/java/com/floralquafloral/registries/stomp/ParsedStomp.java b/src/main/java/com/floralquafloral/registries/stomp/ParsedStomp.java index 4ebc2c2..feeabfe 100644 --- a/src/main/java/com/floralquafloral/registries/stomp/ParsedStomp.java +++ b/src/main/java/com/floralquafloral/registries/stomp/ParsedStomp.java @@ -34,6 +34,7 @@ import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.Objects; public class ParsedStomp { public final Identifier ID; @@ -62,7 +63,7 @@ public ParsedStomp(StompDefinition definition) { this.POST_STOMP_ACTION = definition.getPostStompAction(); } - public void executeServer(MarioServerData data, Entity target, boolean affectMario, boolean harmless, long seed) { + public boolean executeServer(MarioServerData data, Entity target, boolean affectMario, boolean harmless, long seed) { ServerPlayerEntity mario = data.getMario(); // DamageSource damageSource = makeDamageSource(mario.getServerWorld(), this.DAMAGE_TYPE, mario); StompDamageSource stompDamageSource = new StompDamageSource(mario.getServerWorld(), this.DAMAGE_TYPE, mario); @@ -98,13 +99,16 @@ else if (entry.attribute().value().equals(EntityAttributes.GENERIC_ARMOR_TOUGHNE float damage = this.DEFINITION.calculateDamage(data, mario, attackingArmor, armor, target); stompDamageSource.piercing = 2.0F * toughness; - target.damage(stompDamageSource, Math.max(1.0F, damage - 0.6F * stompDamageSource.piercing)); - - if(affectMario) { - this.DEFINITION.executeTravellers(data, target, harmless); - data.setActionTransitionless(RegistryManager.ACTIONS.get(this.POST_STOMP_ACTION)); - StompHandler.networkStomp(data.getMario(), target, this, harmless, seed); + if(target.damage(stompDamageSource, Math.max(1.0F, damage - 0.6F * stompDamageSource.piercing))) { + if(affectMario) { + this.DEFINITION.executeTravellers(data, target, harmless); + if(this.POST_STOMP_ACTION != null) + data.setActionTransitionless(Objects.requireNonNull(RegistryManager.ACTIONS.get(this.POST_STOMP_ACTION))); + StompHandler.networkStomp(data.getMario(), target, this, harmless, seed); + } + return true; } + return false; } public void executeClient(MarioClientSideData data, boolean isSelf, Entity target, boolean harmless, long seed) { if(this.SOUND_EVENT != null) { @@ -124,6 +128,8 @@ public void executeClient(MarioClientSideData data, boolean isSelf, Entity targe if(data instanceof MarioMoveableData moveableData) { moveableData.getTimers().jumpCapped = false; this.DEFINITION.executeTravellers(moveableData, target, harmless); + if(this.POST_STOMP_ACTION != null) + moveableData.setActionTransitionless(Objects.requireNonNull(RegistryManager.ACTIONS.get(this.POST_STOMP_ACTION))); moveableData.applyModifiedVelocity(); } @@ -132,7 +138,7 @@ public void executeClient(MarioClientSideData data, boolean isSelf, Entity targe public boolean attempt(MarioServerData data, Vec3d movement) { ServerPlayerEntity mario = data.getMario(); - List targets = mario.getWorld().getOtherEntities(mario, mario.getBoundingBox().stretch(movement)); + List targets = mario.getWorld().getOtherEntities(mario, mario.getBoundingBox().stretch(movement.multiply(1, 2, 1))); boolean affectMario = true; long seed = RandomSeed.getSeed(); @@ -171,10 +177,7 @@ else if(this.PAINFUL_STOMP_RESPONSE == StompDefinition.PainfulStompResponse.BOUN } - - executeServer(data, target, affectMario, harmless, seed); - - return true; + return executeServer(data, target, affectMario, harmless, seed); } private static DamageSource makeDamageSource(ServerWorld world, RegistryKey key, Entity attacker) { diff --git a/src/main/java/com/floralquafloral/registries/stomp/StompHandler.java b/src/main/java/com/floralquafloral/registries/stomp/StompHandler.java index a740ad1..e2cc769 100644 --- a/src/main/java/com/floralquafloral/registries/stomp/StompHandler.java +++ b/src/main/java/com/floralquafloral/registries/stomp/StompHandler.java @@ -70,7 +70,7 @@ public static void registerReceiver() { } MarioPlayerData data = getMarioData(mario); stompType.executeClient((MarioClientSideData) data, mario.isMainPlayer(), target, payload.harmless, payload.seed); - data.setActionTransitionless(RegistryManager.ACTIONS.get(stompType.POST_STOMP_ACTION)); +// data.setActionTransitionless(RegistryManager.ACTIONS.get(stompType.POST_STOMP_ACTION)); }); } diff --git a/src/main/java/com/floralquafloral/registries/stomp/basestomptypes/GroundPoundStomp.java b/src/main/java/com/floralquafloral/registries/stomp/basestomptypes/GroundPoundStomp.java new file mode 100644 index 0000000..83de95c --- /dev/null +++ b/src/main/java/com/floralquafloral/registries/stomp/basestomptypes/GroundPoundStomp.java @@ -0,0 +1,71 @@ +package com.floralquafloral.registries.stomp.basestomptypes; + +import com.floralquafloral.MarioQuaMario; +import com.floralquafloral.mariodata.MarioClientSideData; +import com.floralquafloral.mariodata.MarioData; +import com.floralquafloral.mariodata.moveable.MarioTravelData; +import com.floralquafloral.registries.stomp.StompDefinition; +import com.floralquafloral.registries.stomp.StompHandler; +import com.floralquafloral.stats.CharaStat; +import com.floralquafloral.stats.StatCategory; +import com.floralquafloral.util.MarioSFX; +import net.minecraft.entity.Entity; +import net.minecraft.entity.MovementType; +import net.minecraft.item.ItemStack; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.sound.SoundEvent; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.Vec3d; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class GroundPoundStomp implements StompDefinition { + @Override public @NotNull Identifier getID() { + return Identifier.of(MarioQuaMario.MOD_ID, "ground_pound"); + } + + public final CharaStat BASE_DAMAGE = new CharaStat(7, StatCategory.STOMP_BASE_DAMAGE); + + @Override public boolean mustFallOnTarget() { + return false; + } + + @Override public @NotNull PainfulStompResponse getPainfulStompResponse() { + return PainfulStompResponse.INJURY; + } + + @Override public boolean shouldAttemptMounting() { + return true; + } + + @Override public boolean canHitNonLiving() { + return true; + } + + @Override public @NotNull Identifier getDamageType() { + return Identifier.of(MarioQuaMario.MOD_ID, "ground_pound"); + } + @Override public @Nullable SoundEvent getSoundEvent() { + return MarioSFX.KICK; + } + + @Override public @Nullable Identifier getPostStompAction() { + return null; + } + + @Override public boolean canStompTarget(MarioData data, Entity target) { + return !target.getType().isIn(StompHandler.IMMUNE_TO_BASIC_STOMP_TAG); + } + + @Override public float calculateDamage(MarioData data, ServerPlayerEntity mario, ItemStack equipment, float equipmentArmorValue, Entity target) { + return ((float) BASE_DAMAGE.get(data)) + equipmentArmorValue; + } + + @Override public void executeTravellers(MarioTravelData data, Entity target, boolean harmless) { + double deltaY = data.getMario().getY() - (target.getY() - target.getHeight()); + } + + @Override public void executeClients(MarioClientSideData data, boolean isSelf, Entity target, boolean harmless, long seed) { + + } +} diff --git a/src/main/java/com/floralquafloral/registries/stomp/basestomptypes/JumpStomp.java b/src/main/java/com/floralquafloral/registries/stomp/basestomptypes/JumpStomp.java index 6a56316..0d252e0 100644 --- a/src/main/java/com/floralquafloral/registries/stomp/basestomptypes/JumpStomp.java +++ b/src/main/java/com/floralquafloral/registries/stomp/basestomptypes/JumpStomp.java @@ -63,8 +63,15 @@ public class JumpStomp implements StompDefinition { } @Override public void executeTravellers(MarioTravelData data, Entity target, boolean harmless) { - double deltaY = data.getMario().getY() - (target.getY() - target.getHeight()); - data.getMario().move(MovementType.PISTON, new Vec3d(0, deltaY, 0)); + double deltaY = (target.getY() + target.getHeight()) - data.getMario().getY(); +// MarioQuaMario.LOGGER.info("executeTravellers 1:" +// + "\nTarget: " + target +// + "\nTargetY: " + (target.getY() + target.getHeight()) +// + "\nMarioY: " + data.getMario().getY() +// + "\ndeltaY: " + (data.getMario().getY()) +// ); + data.getMario().move(MovementType.SELF, new Vec3d(0, deltaY, 0)); +// data.getMario().setPos(data.getMario().getX(), target.getY() + target.getHeight(), data.getMario().getZ()); data.setYVel(BOUNCE_VEL.get(data)); } diff --git a/src/main/java/com/floralquafloral/util/MarioSFX.java b/src/main/java/com/floralquafloral/util/MarioSFX.java index f6a1f28..c16c20e 100644 --- a/src/main/java/com/floralquafloral/util/MarioSFX.java +++ b/src/main/java/com/floralquafloral/util/MarioSFX.java @@ -24,6 +24,7 @@ public final class MarioSFX { public static final SoundEvent STOMP_SPIN = makeStompSound("spin"); public static final SoundEvent STOMP_HEAVY = makeStompSound("heavy"); public static final SoundEvent STOMP_YOSHI = makeStompSound("yoshi"); + public static final SoundEvent KICK = makeStompSound("kick"); public static final SoundEvent DUCK = makeActionSound("duck"); public static final SoundEvent UNDUCK = makeActionSound("unduck"); diff --git a/src/main/resources/assets/qua_mario/lang/en_us.json b/src/main/resources/assets/qua_mario/lang/en_us.json index 8f90a58..07c90a8 100644 --- a/src/main/resources/assets/qua_mario/lang/en_us.json +++ b/src/main/resources/assets/qua_mario/lang/en_us.json @@ -41,6 +41,7 @@ "subtitles.qua_mario.stomp.spin": "Something gets stomped", "subtitles.qua_mario.stomp.heavy": "Something gets stomped", "subtitles.qua_mario.stomp.yoshi": "Something gets crushed", + "subtitles.qua_mario.stomp.kick": "Something gets attacked", "subtitles.qua_mario.action.duck": "Ducking", "subtitles.qua_mario.action.unduck": "Un-ducking", "subtitles.qua_mario.action.ground_pound_pre": "Aerial flip", diff --git a/src/main/resources/assets/qua_mario/sounds.json b/src/main/resources/assets/qua_mario/sounds.json index 67d3e6f..e635b76 100644 --- a/src/main/resources/assets/qua_mario/sounds.json +++ b/src/main/resources/assets/qua_mario/sounds.json @@ -89,6 +89,12 @@ "qua_mario:sfx/stomp/yoshi" ] }, + "sfx.stomp.kick": { + "subtitle": "subtitles.qua_mario.stomp.kick", + "sounds": [ + "qua_mario:sfx/stomp/kick" + ] + }, "sfx.action.duck": { "subtitle": "subtitles.qua_mario.action.duck", "sounds": [ diff --git a/src/main/resources/assets/qua_mario/sounds/sfx/stomp/kick.ogg b/src/main/resources/assets/qua_mario/sounds/sfx/stomp/kick.ogg new file mode 100644 index 0000000..b4c84cd Binary files /dev/null and b/src/main/resources/assets/qua_mario/sounds/sfx/stomp/kick.ogg differ diff --git a/src/main/resources/data/minecraft/tags/damage_type/panic_causes.json b/src/main/resources/data/minecraft/tags/damage_type/panic_causes.json new file mode 100644 index 0000000..e27dd75 --- /dev/null +++ b/src/main/resources/data/minecraft/tags/damage_type/panic_causes.json @@ -0,0 +1,8 @@ +{ + "replace": false, + "values": [ + "qua_mario:stomp", + "qua_mario:spin_jump", + "qua_mario:ground_pound" + ] +} \ No newline at end of file diff --git a/src/main/resources/data/qua_mario/tags/block/always_repeat_bump.json b/src/main/resources/data/qua_mario/tags/block/always_repeat_bump.json new file mode 100644 index 0000000..266975d --- /dev/null +++ b/src/main/resources/data/qua_mario/tags/block/always_repeat_bump.json @@ -0,0 +1,6 @@ +{ + "values": [ + "minecraft:spawner", + "minecraft:trial_spawner" + ] +} \ No newline at end of file diff --git a/src/main/resources/data/qua_mario/tags/block/bump_regardless_of_hardness.json b/src/main/resources/data/qua_mario/tags/block/bump_regardless_of_hardness.json index 34ca73b..afd59ab 100644 --- a/src/main/resources/data/qua_mario/tags/block/bump_regardless_of_hardness.json +++ b/src/main/resources/data/qua_mario/tags/block/bump_regardless_of_hardness.json @@ -1,5 +1,6 @@ { "values": [ - + "minecraft:dispenser", + "minecraft:dropper" ] } \ No newline at end of file diff --git a/src/main/resources/data/qua_mario/tags/block/never_repeat_bump.json b/src/main/resources/data/qua_mario/tags/block/never_repeat_bump.json new file mode 100644 index 0000000..49f3d03 --- /dev/null +++ b/src/main/resources/data/qua_mario/tags/block/never_repeat_bump.json @@ -0,0 +1,8 @@ +{ + "values": [ + "minecraft:redstone_lamp", + "minecraft:piston", + "minecraft:sticky_piston", + "minecraft:piston_head" + ] +} \ No newline at end of file diff --git a/src/main/resources/data/qua_mario/tags/block/resistant_to_ceiling_bumps.json b/src/main/resources/data/qua_mario/tags/block/resistant_to_ceiling_bumps.json new file mode 100644 index 0000000..34ca73b --- /dev/null +++ b/src/main/resources/data/qua_mario/tags/block/resistant_to_ceiling_bumps.json @@ -0,0 +1,5 @@ +{ + "values": [ + + ] +} \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index f775710..d520159 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -15,10 +15,6 @@ "icon": "assets/qua_mario/icon.png", "environment": "*", "entrypoints": { - "mario-stomp-types": [ - "com.floralquafloral.registries.stomp.basestomptypes.JumpStomp" - ], - "mario-actions-uncategorized": [ "com.floralquafloral.registries.states.action.baseactions.ActionDebug", "com.floralquafloral.registries.states.action.baseactions.ActionDebugAlt", @@ -42,7 +38,9 @@ "com.floralquafloral.registries.states.action.baseactions.airborne.DuckJump", "com.floralquafloral.registries.states.action.baseactions.airborne.LongJump", "com.floralquafloral.registries.states.action.baseactions.airborne.Stomp", - "com.floralquafloral.registries.states.action.baseactions.airborne.Backflip" + "com.floralquafloral.registries.states.action.baseactions.airborne.Backflip", + "com.floralquafloral.registries.states.action.baseactions.airborne.DoubleJump", + "com.floralquafloral.registries.states.action.baseactions.airborne.TripleJump" ], "mario-actions-aquatic": [ @@ -58,9 +56,15 @@ "com.floralquafloral.registries.states.character.basecharacters.Toadette" ], + "mario-stomp-types": [ + "com.floralquafloral.registries.stomp.basestomptypes.JumpStomp", + "com.floralquafloral.registries.stomp.basestomptypes.GroundPoundStomp" + ], + "mario-bumping-handlers": [ "com.floralquafloral.bumping.handlers.TrapdoorBumpingHandler", - "com.floralquafloral.bumping.handlers.PistonBumpingHandler" + "com.floralquafloral.bumping.handlers.PistonBumpingHandler", + "com.floralquafloral.bumping.handlers.SpawnerBumpingHandler" ], "main": [