Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions MODIFIERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,10 @@ These effects are applied when hurting enemies.
**id:** `pummeling` | **crafting:** `minecraft:anvil` ![anvil](https://raw.githubusercontent.com/anish-shanbhag/minecraft-api/master/public/images/items/anvil.png)

**Decription:** Slams enemies into the ground
### Riftwalk
**id:** `riftwalk` | **crafting:** `minecraft:chorus_flower` ![chorus_flower](https://raw.githubusercontent.com/anish-shanbhag/minecraft-api/master/public/images/items/chorus_flower.png)

**Decription:** 15% chance to teleport behind your target after hitting them, dealing bonus damage on the next hit.
### Scorched
**id:** `scorched` | **crafting:** `minecraft:blaze_powder` ![blaze_powder](https://raw.githubusercontent.com/anish-shanbhag/minecraft-api/master/public/images/items/blaze_powder.png)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public static Modifier getModifier(String name) {
public static Modifier PUMMELING = register(new Pummeling());
public static Modifier HAILEYS_WRATH = register(new HaileysWrath());
public static Modifier EARLY_BIRD = register(new EarlyBird());
public static Modifier RIFTWALK = register(new Riftwalk());

// Biome-restricted modifiers
public static Modifier AQUATIC = register(new Aquatic());
Expand Down Expand Up @@ -103,7 +104,7 @@ public static Modifier getModifier(String name) {
public static final Set<Modifier> BREAKERS = Set.of(EXPLODE, LEARNING, ATTRACTING, VEINY, MELTING, EXCAVATOR, PROSPECTOR, MUNCHIES, FRAGILE, LUMBERING);
public static final Set<Modifier> USERS = Set.of(TORCH_PLACE, DIRT_PLACE, FIRE_PLACE, FIRE_BALL, VOID_TOUCHED);
public static final Set<Modifier> HURTERS = Set.of(CRITICAL, CHARGING, FLAMING, COMBO, DRAINING, POISONOUS,
WITHERING, BLINDING, BEZERK, NEMESIS, SOULBOUND, SCORCHED, FROZEN, OVERGROWN, FIERCE, FEASTING, EXECUTIONER, CROWD_PLEASER, PUMMELING, HAILEYS_WRATH, MUNCHIES, CHAOTIC, FRAGILE, CLUNKY, EARLY_BIRD);
WITHERING, BLINDING, BEZERK, NEMESIS, SOULBOUND, SCORCHED, FROZEN, OVERGROWN, FIERCE, FEASTING, EXECUTIONER, CROWD_PLEASER, PUMMELING, HAILEYS_WRATH, MUNCHIES, CHAOTIC, FRAGILE, CLUNKY, EARLY_BIRD, RIFTWALK);
public static final Set<Modifier> HOLDERS = Set.of(HASTY, ABSORBTION, FILLING, RAINY, ORE_FINDER, SPAWNER_FINDER,
LIVING, REGENERATING, RESISTANT, FIRE_RESISTANT, AQUATIC, HUNTER, FEASTING, NATURALIST, CLUNKY);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package dev.marston.randomloot.loot.modifiers.hurter;

import dev.marston.randomloot.loot.LootItem.ToolType;
import dev.marston.randomloot.loot.modifiers.EntityHurtModifier;
import dev.marston.randomloot.loot.modifiers.Modifier;
import net.minecraft.ChatFormatting;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;

import java.util.List;
import java.util.Random;

public class Riftwalk implements EntityHurtModifier {

private String name;
private static final float TELEPORT_CHANCE = 0.15f; // 15% chance to teleport behind enemy
private static final double TELEPORT_RANGE = 3.0; // Teleport up to 3 blocks behind
private Random random = new Random();

public Riftwalk() {
this("Riftwalk");
}

public Riftwalk(String name) {
this.name = name;
}

public Modifier clone() {
return new Riftwalk();
}

@Override
public CompoundTag toNBT() {
CompoundTag tag = new CompoundTag();
tag.putString(NAME, name);
return tag;
}

@Override
public Modifier fromNBT(CompoundTag tag) {
return new Riftwalk(tag.getStringOr(NAME, "Riftwalk"));
}

@Override
public String name() {
return name;
}

@Override
public String tagName() {
return "riftwalk";
}

@Override
public String color() {
return ChatFormatting.DARK_BLUE.getName();
}

@Override
public String description() {
return "15% chance to teleport behind your target after hitting them, dealing bonus damage on the next hit.";
}

@Override
public void writeToLore(List<Component> list, boolean shift) {
MutableComponent comp = Modifier.makeComp(this.name(), this.color());
list.add(comp);
}

@Override
public boolean forTool(ToolType type) {
return type.equals(ToolType.SWORD) || type.equals(ToolType.AXE);
}

private void teleportBehindTarget(LivingEntity attacker, LivingEntity target, Level level) {
if (level.isClientSide()) {
return;
}

// Calculate position behind the target
double angle = Math.atan2(target.getZ() - attacker.getZ(), target.getX() - attacker.getX());

// Teleport distance (3 blocks behind)
double teleportX = target.getX() - Math.cos(angle) * TELEPORT_RANGE;
double teleportZ = target.getZ() - Math.sin(angle) * TELEPORT_RANGE;
double teleportY = target.getY();

// Store old position
double oldX = attacker.getX();
double oldY = attacker.getY();
double oldZ = attacker.getZ();

// Teleport attacker
attacker.teleportTo(teleportX, teleportY, teleportZ);

// Play sound at old position
if (level instanceof ServerLevel serverLevel) {
serverLevel.playSound(
null,
oldX, oldY, oldZ,
SoundEvents.ENDERMAN_TELEPORT,
SoundSource.PLAYERS,
1.0f, 1.0f
);

// Particles at old position
for (int i = 0; i < 16; i++) {
serverLevel.sendParticles(
ParticleTypes.PORTAL,
oldX, oldY + 1.0, oldZ,
1,
random.nextGaussian() * 0.5,
random.nextGaussian() * 0.5,
random.nextGaussian() * 0.5,
0.5
);
}

// Sound at new position
serverLevel.playSound(
null,
teleportX, teleportY, teleportZ,
SoundEvents.ENDERMAN_TELEPORT,
SoundSource.PLAYERS,
1.0f, 1.2f
);

// Particles at new position
for (int i = 0; i < 16; i++) {
serverLevel.sendParticles(
ParticleTypes.PORTAL,
teleportX, teleportY + 1.0, teleportZ,
1,
random.nextGaussian() * 0.5,
random.nextGaussian() * 0.5,
random.nextGaussian() * 0.5,
0.5
);
}
}
}

@Override
public boolean hurtEnemy(ItemStack itemstack, LivingEntity hurtee, LivingEntity hurter) {
Level level = hurtee.level();

// 15% chance to trigger riftwalk
if (random.nextFloat() < TELEPORT_CHANCE) {
teleportBehindTarget(hurter, hurtee, level);
}

return false;
}

@Override
public boolean compatible(Modifier mod) {
// Incompatible with Void-Touched (another teleport modifier)
return !mod.tagName().equals("void_touched");
}
}
8 changes: 8 additions & 0 deletions src/main/resources/data/randomloot/recipe/trait_riftwalk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"type": "randomloot:trait_change",
"item": {
"count": 1,
"id": "minecraft:chorus_flower"
},
"trait": "riftwalk"
}
Loading