Skip to content

Commit

Permalink
Reimplement self destructive using a potion effect
Browse files Browse the repository at this point in the history
Automatically handles the ticking behavior, and makes it easier to apply to enderslimes later. Plus, visual indicator of explosion, both from your point of view and others
  • Loading branch information
KnightMiner committed May 23, 2022
1 parent c91e10b commit 40a668a
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@
import slimeknights.tconstruct.tools.modifiers.traits.skull.PlagueModifier;
import slimeknights.tconstruct.tools.modifiers.traits.skull.RevengeModifier;
import slimeknights.tconstruct.tools.modifiers.traits.skull.SelfDestructiveModifier;
import slimeknights.tconstruct.tools.modifiers.traits.skull.SelfDestructiveModifier.SelfDestructiveEffect;
import slimeknights.tconstruct.tools.modifiers.traits.skull.StrongBonesModifier;
import slimeknights.tconstruct.tools.modifiers.traits.skull.WildfireModifier;
import slimeknights.tconstruct.tools.modifiers.traits.skull.WitheredModifier;
Expand Down Expand Up @@ -420,6 +421,8 @@ public TinkerModifiers() {
public static RegistryObject<TinkerEffect> teleportCooldownEffect = MOB_EFFECTS.register("teleport_cooldown", () -> new NoMilkEffect(MobEffectCategory.HARMFUL, 0xCC00FA, true));
public static RegistryObject<TinkerEffect> fireballCooldownEffect = MOB_EFFECTS.register("fireball_cooldown", () -> new NoMilkEffect(MobEffectCategory.HARMFUL, 0xFC9600, true));
public static RegistryObject<TinkerEffect> calcifiedEffect = MOB_EFFECTS.register("calcified", () -> new NoMilkEffect(MobEffectCategory.BENEFICIAL, -1, true));
public static RegistryObject<TinkerEffect> selfDestructiveEffect = MOB_EFFECTS.register("self_destructing", SelfDestructiveEffect::new);


/*
* Recipes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,73 +2,45 @@

import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.effect.MobEffectCategory;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import net.minecraft.world.entity.ai.attributes.AttributeModifier.Operation;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Explosion;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.TickEvent.Phase;
import net.minecraftforge.event.TickEvent.PlayerTickEvent;
import net.minecraftforge.eventbus.api.EventPriority;
import slimeknights.tconstruct.TConstruct;
import slimeknights.tconstruct.library.modifiers.hooks.IArmorInteractModifier;
import slimeknights.tconstruct.library.modifiers.impl.NoLevelsModifier;
import slimeknights.tconstruct.library.tools.capability.TinkerDataCapability;
import slimeknights.tconstruct.library.tools.capability.TinkerDataCapability.TinkerDataKey;
import slimeknights.tconstruct.library.tools.context.EquipmentChangeContext;
import slimeknights.tconstruct.library.tools.nbt.IToolStackView;
import slimeknights.tconstruct.tools.TinkerModifiers;
import slimeknights.tconstruct.tools.modifiers.effect.NoMilkEffect;

import javax.annotation.Nullable;
import java.util.UUID;

public class SelfDestructiveModifier extends NoLevelsModifier implements IArmorInteractModifier {
private static final AttributeModifier SPEED_MODIFIER = new AttributeModifier(UUID.fromString("68ee3026-1d50-4eb4-914e-a8b05fbfdb71"), TConstruct.prefix("self_destruct_slowdown"), -0.9f, Operation.MULTIPLY_TOTAL);
/** Self damage source */
private static final DamageSource SELF_DESTRUCT = (new DamageSource(TConstruct.prefix("self_destruct"))).bypassArmor().setExplosion();
/** Key for the time the fuse finises */
private static final TinkerDataKey<Integer> FUSE_FINISH = TConstruct.createKey("self_destruct_finish");

public SelfDestructiveModifier() {
MinecraftForge.EVENT_BUS.addListener(EventPriority.NORMAL, false, PlayerTickEvent.class, SelfDestructiveModifier::playerTick);
}

@Override
public boolean startArmorInteract(IToolStackView tool, int level, Player player, EquipmentSlot slot) {
if (player.isShiftKeyDown()) {
player.getCapability(TinkerDataCapability.CAPABILITY).ifPresent(data -> data.put(FUSE_FINISH, player.tickCount + 30));
TinkerModifiers.selfDestructiveEffect.get().apply(player, 30, 2, true);
player.playSound(SoundEvents.CREEPER_PRIMED, 1.0F, 0.5F);
// make the player slow
AttributeInstance instance = player.getAttributes().getInstance(Attributes.MOVEMENT_SPEED);
if (instance != null && !instance.hasModifier(SPEED_MODIFIER)) {
instance.addTransientModifier(SPEED_MODIFIER);
}
return true;
}
return false;
}

/** Restores speed to full */
private static void restoreSpeed(LivingEntity livingEntity) {
AttributeInstance instance = livingEntity.getAttributes().getInstance(Attributes.MOVEMENT_SPEED);
if (instance != null) {
instance.removeModifier(SPEED_MODIFIER);
}
}

@Override
public void stopArmorInteract(IToolStackView tool, int level, Player player, EquipmentSlot slot) {
player.getCapability(TinkerDataCapability.CAPABILITY).ifPresent(data -> data.remove(FUSE_FINISH));
restoreSpeed(player);
player.removeEffect(TinkerModifiers.selfDestructiveEffect.get());
}

@Override
public void onUnequip(IToolStackView tool, int level, EquipmentChangeContext context) {
context.getTinkerData().ifPresent(data -> data.remove(FUSE_FINISH));
restoreSpeed(context.getEntity());
context.getEntity().removeEffect(TinkerModifiers.selfDestructiveEffect.get());
}

@Nullable
Expand All @@ -77,20 +49,26 @@ public <T> T getModule(Class<T> type) {
return tryModuleMatch(type, IArmorInteractModifier.class, this);
}

/** Called on player tick to update the fuse */
private static void playerTick(PlayerTickEvent event) {
if (event.phase == Phase.START && !event.player.level.isClientSide && !event.player.isSpectator()) {
event.player.getCapability(TinkerDataCapability.CAPABILITY).ifPresent(data -> {
Integer fuseFinish = data.get(FUSE_FINISH);
if (fuseFinish != null && fuseFinish <= event.player.tickCount) {
event.player.level.explode(event.player, event.player.getX(), event.player.getY(), event.player.getZ(), 3, Explosion.BlockInteraction.DESTROY);
event.player.hurt(SELF_DESTRUCT, 99999);
if (event.player.getHealth() > 0) {
restoreSpeed(event.player);
}
data.remove(FUSE_FINISH);
}
});
/** Internal potion effect handling the explosion */
public static class SelfDestructiveEffect extends NoMilkEffect {
public SelfDestructiveEffect() {
super(MobEffectCategory.HARMFUL, 0x59D24A, true);
// make the player slow
addAttributeModifier(Attributes.MOVEMENT_SPEED, "68ee3026-1d50-4eb4-914e-a8b05fbfdb71", -0.9f, Operation.MULTIPLY_TOTAL);
}

@Override
public boolean isDurationEffectTick(int duration, int amplifier) {
return duration == 1;
}

@Override
public void applyEffectTick(LivingEntity living, int amplifier) {
// effect level is the explosion radius
if (!living.level.isClientSide) {
living.level.explode(living, living.getX(), living.getY(), living.getZ(), amplifier + 1, Explosion.BlockInteraction.DESTROY);
living.hurt(SELF_DESTRUCT, 99999);
}
}
}
}
2 changes: 2 additions & 0 deletions src/main/resources/assets/tconstruct/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -2264,6 +2264,8 @@
"effect.tconstruct.teleport_cooldown": "Teleport Cooldown",
"effect.tconstruct.fireball_cooldown": "Fireball Cooldown",
"effect.tconstruct.calcified": "Calcified",
"effect.tconstruct.self_destructing": "Self Destructing",


"_comment": "Roman numerals",
"roman_numeral.value.1": "I",
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 40a668a

Please sign in to comment.