Skip to content

Commit 0816a07

Browse files
committed
spear features for attribute swapping
1 parent 47a4ad5 commit 0816a07

1 file changed

Lines changed: 99 additions & 0 deletions

File tree

src/main/java/meteordevelopment/meteorclient/systems/modules/combat/AttributeSwap.java

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,15 @@
2929
import net.minecraft.registry.tag.EntityTypeTags;
3030
import net.minecraft.registry.tag.ItemTags;
3131
import net.minecraft.util.hit.HitResult;
32+
import net.minecraft.util.math.Box;
33+
import net.minecraft.util.math.Vec3d;
3234

3335
public class AttributeSwap extends Module {
3436
private final SettingGroup sgGeneral = settings.getDefaultGroup();
3537
private final SettingGroup sgSwappingOptions = settings.createGroup("Swapping Options");
3638
private final SettingGroup sgSwordEnchants = settings.createGroup("Sword Enchants");
3739
private final SettingGroup sgMaceEnchants = settings.createGroup("Mace Enchants");
40+
private final SettingGroup sgSpearEnchants = settings.createGroup("Spear Enchants");
3841
private final SettingGroup sgOtherEnchants = settings.createGroup("Other Enchants");
3942
private final SettingGroup sgWeapon = settings.createGroup("Weapon Options");
4043

@@ -120,6 +123,14 @@ public class AttributeSwap extends Module {
120123
.build()
121124
);
122125

126+
private final Setting<Boolean> spearSwapping = sgSwappingOptions.add(new BoolSetting.Builder()
127+
.name("spear-swapping")
128+
.description("Enables smart swapping for spear enchantments.")
129+
.defaultValue(true)
130+
.visible(() -> mode.get() == Mode.Smart)
131+
.build()
132+
);
133+
123134
private final Setting<Boolean> enchantFireAspect = sgSwordEnchants.add(new BoolSetting.Builder()
124135
.name("fire-aspect")
125136
.description("Swaps to an item with Fire Aspect to set the target on fire, if target isn't already on fire")
@@ -208,6 +219,30 @@ public class AttributeSwap extends Module {
208219
.build()
209220
);
210221

222+
private final Setting<Boolean> enchantLunge = sgSpearEnchants.add(new BoolSetting.Builder()
223+
.name("lunge")
224+
.description("Swaps to a spear with Lunge for traveling.")
225+
.defaultValue(true)
226+
.visible(() -> mode.get() == Mode.Smart && spearSwapping.get())
227+
.build()
228+
);
229+
230+
private final Setting<Boolean> spearHitbox = sgSpearEnchants.add(new BoolSetting.Builder()
231+
.name("hitbox")
232+
.description("Swaps to a spear for extended reach when target is far.")
233+
.defaultValue(true)
234+
.visible(() -> mode.get() == Mode.Smart && spearSwapping.get())
235+
.build()
236+
);
237+
238+
private final Setting<Boolean> excludeLungeFromHitbox = sgSpearEnchants.add(new BoolSetting.Builder()
239+
.name("exclude-lunge-from-hitbox")
240+
.description("Don't use lunge-enchanted spears for hitbox extension.")
241+
.defaultValue(true)
242+
.visible(() -> mode.get() == Mode.Smart && spearSwapping.get() && spearHitbox.get())
243+
.build()
244+
);
245+
211246
private final Setting<Boolean> onlyOnWeapon = sgWeapon.add(new BoolSetting.Builder()
212247
.name("only-on-weapon")
213248
.description("Only swaps when holding a selected weapon in hand.")
@@ -286,6 +321,29 @@ public void onDeactivate() {
286321

287322
@EventHandler
288323
private void onAttack(DoAttackEvent event) {
324+
if (mode.get() == Mode.Smart && spearSwapping.get()) {
325+
326+
if (spearHitbox.get()) {
327+
Entity target = getTargetEntity(7);
328+
if (target != null) {
329+
if (mc.player.distanceTo(target) <= 3.5) return;
330+
int spearSlot = getSmartSpearSlot(false);
331+
if (spearSlot != -1) {
332+
doSwap(spearSlot);
333+
return;
334+
}
335+
}
336+
}
337+
// lunge spear for travelling (or when enemy isn't in spear range)
338+
if (enchantLunge.get()) {
339+
int lungeSlot = getSmartSpearSlot(true);
340+
if (lungeSlot != -1) {
341+
doSwap(lungeSlot);
342+
return;
343+
}
344+
}
345+
}
346+
289347
if (!canSwapByWeapon() || mode.get() == Mode.Smart || !swapOnMiss.get()) return;
290348
if (mc.crosshairTarget.getType() == HitResult.Type.BLOCK) return;
291349

@@ -382,6 +440,47 @@ private int getSmartSlot(Entity target) {
382440
return bestSlot;
383441
}
384442

443+
private int getSmartSpearSlot(boolean requireLunge) {
444+
for (int i = 0; i < 9; i++) {
445+
if (i == mc.player.getInventory().getSelectedSlot()) continue;
446+
ItemStack stack = mc.player.getInventory().getStack(i);
447+
if (!stack.isIn(ItemTags.SPEARS)) continue;
448+
449+
boolean hasLunge = Utils.getEnchantmentLevel(stack, Enchantments.LUNGE) > 0;
450+
if (requireLunge && !hasLunge) continue;
451+
if (!requireLunge && excludeLungeFromHitbox.get() && hasLunge) continue;
452+
453+
return i;
454+
}
455+
return -1;
456+
}
457+
458+
private Entity getTargetEntity(double maxDistance) {
459+
Vec3d start = mc.player.getCameraPosVec(1.0f);
460+
Vec3d look = mc.player.getRotationVec(1.0f);
461+
Vec3d end = start.add(look.multiply(maxDistance));
462+
463+
Box box = mc.player.getBoundingBox().stretch(look.multiply(maxDistance)).expand(1.0);
464+
465+
Entity target = null;
466+
double closestDistance = maxDistance * maxDistance;
467+
468+
for (Entity entity : mc.world.getOtherEntities(mc.player, box, e -> !e.isSpectator() && e.canHit())) {
469+
// expanding entity's hitbox by 0.15 to simulate spear's actual hitbox margin
470+
Box expandedBox = entity.getBoundingBox().expand(0.150);
471+
472+
if (expandedBox.raycast(start, end).isPresent()) {
473+
double distSq = start.squaredDistanceTo(entity.getX(), entity.getY(), entity.getZ());
474+
if (distSq < closestDistance) {
475+
closestDistance = distSq;
476+
target = entity;
477+
}
478+
}
479+
}
480+
481+
return target;
482+
}
483+
385484
private double getItemScore(ItemStack stack, boolean isFalling, boolean durability, boolean isLiving, boolean isPlayer, boolean isOnFire, boolean hasFireResistance, boolean isUndead, boolean isArthropod, boolean isAquatic, double armor, float health) {
386485
double score = 0;
387486

0 commit comments

Comments
 (0)