Fixed stuff that madness needed

This commit is contained in:
2025-05-15 15:21:35 -05:00
parent dbe0b8a4f4
commit c9e1e4e7c1
12 changed files with 275 additions and 145 deletions

View File

@@ -89,10 +89,10 @@ public class AdminCommand implements QuickCommand {
switch (args.get(1).toString()) { switch (args.get(1).toString()) {
case "vector" -> { case "vector" -> {
if (!(commandSender instanceof Player p)) return; if (!(commandSender instanceof Player p)) return;
CustomDisplayRaytracer.traceWithReflection(p.getEyeLocation(),p.getEyeLocation().getDirection(),60,0.1,6,point -> { CustomDisplayRaytracer.traceWithReflection(p.getEyeLocation(),p.getEyeLocation().getDirection(),60,0.5,60,point -> {
DisplayUtils.DUST_PARTICLE_FACTORY.apply(Color.AQUA,1F).accept(point.getLoc()); DisplayUtils.DUST_PARTICLE_FACTORY.apply(Color.AQUA,1F).accept(point.getLoc());
return CustomDisplayRaytracer.hitBlockIf(block -> !block.isPassable()).test(point); return false;
},(point,block) -> { },(point,block) -> {
DisplayUtils.sphere(point.getLoc(),0.3,0.1,0.1,loc -> { DisplayUtils.sphere(point.getLoc(),0.3,0.1,0.1,loc -> {
DisplayUtils.DUST_PARTICLE_FACTORY.apply(Color.RED,1F).accept(loc); DisplayUtils.DUST_PARTICLE_FACTORY.apply(Color.RED,1F).accept(loc);
@@ -100,7 +100,7 @@ public class AdminCommand implements QuickCommand {
return true; return true;
},(point,entity) -> { },(point,entity) -> {
return false; return !p.equals(entity);
}); });
} }
} }

View File

@@ -6,19 +6,19 @@ import me.trouper.trimserver.server.systems.abilities.AbstractAbility;
import me.trouper.trimserver.server.systems.abilities.PatternInfo; import me.trouper.trimserver.server.systems.abilities.PatternInfo;
import me.trouper.trimserver.utils.SoundPlayer; import me.trouper.trimserver.utils.SoundPlayer;
import me.trouper.trimserver.utils.TargetingUtils; import me.trouper.trimserver.utils.TargetingUtils;
import me.trouper.trimserver.utils.Text;
import me.trouper.trimserver.utils.visual.BlockDisplayRaytracer; import me.trouper.trimserver.utils.visual.BlockDisplayRaytracer;
import org.bukkit.Location; import org.bukkit.*;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.Sound;
import org.bukkit.damage.DamageSource; import org.bukkit.damage.DamageSource;
import org.bukkit.damage.DamageType; import org.bukkit.damage.DamageType;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.meta.trim.TrimPattern; import org.bukkit.inventory.meta.trim.TrimPattern;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@PatternInfo(name = "Bolt", description = "Summon a bolt of lightning at enemies. Includes Variants.") @PatternInfo(name = "Bolt", description = "Summon a bolt of lightning at enemies. Includes Variants.")
public class BoltAbility extends AbstractAbility implements Main { public class BoltAbility extends AbstractAbility implements Main {
@@ -31,6 +31,25 @@ public class BoltAbility extends AbstractAbility implements Main {
return TargetingUtils.areaAffect(caster.getLocation(),range,target-> !main.man().trustBackend.trusts(caster,target),(target)->{ return TargetingUtils.areaAffect(caster.getLocation(),range,target-> !main.man().trustBackend.trusts(caster,target),(target)->{
drawLightning(caster.getEyeLocation(),target.getEyeLocation(),innerBlock,outerBlock); drawLightning(caster.getEyeLocation(),target.getEyeLocation(),innerBlock,outerBlock);
target.damage(damage,DamageSource.builder(DamageType.LIGHTNING_BOLT).withDamageLocation(caster.getEyeLocation()).withDirectEntity(caster).build()); target.damage(damage,DamageSource.builder(DamageType.LIGHTNING_BOLT).withDamageLocation(caster.getEyeLocation()).withDirectEntity(caster).build());
if (target instanceof Player t) Text.sendMessage(Text.Pallet.INFO,t,"You have been stunned by {0}'s Bolt!",caster.name());
AtomicInteger counter = new AtomicInteger(0);
Bukkit.getScheduler().runTaskTimer(main.getPlugin(),(task) -> {
if (counter.getAndIncrement() > 40) {
task.cancel();
return;
}
int tick = target.getNoDamageTicks();
int maxTick = target.getMaximumNoDamageTicks();
target.setNoDamageTicks(1);
target.setMaximumNoDamageTicks(2);
target.damage(0.01,DamageSource.builder(DamageType.LIGHTNING_BOLT).withDamageLocation(caster.getLocation()).withDirectEntity(caster).build());
target.setNoDamageTicks(tick);
target.setMaximumNoDamageTicks(maxTick);
Location stunLoc = target.getLocation().clone();
target.teleport(stunLoc);
},0,1);
}); });
} }
@@ -48,7 +67,9 @@ public class BoltAbility extends AbstractAbility implements Main {
direction.normalize().multiply(segmentLength); direction.normalize().multiply(segmentLength);
SoundPlayer bolt = new SoundPlayer(end, Sound.ENTITY_LIGHTNING_BOLT_THUNDER,10,1); SoundPlayer bolt = new SoundPlayer(end, Sound.ENTITY_LIGHTNING_BOLT_THUNDER,10,1);
SoundPlayer ring = new SoundPlayer(end, Sound.ITEM_TRIDENT_THUNDER,10,1); SoundPlayer ring = new SoundPlayer(end, Sound.ITEM_TRIDENT_THUNDER,10,1);
SoundPlayer zip = new SoundPlayer(end, Sound.ENTITY_BEE_STING,10,1);
zip.playWithin(30 );
bolt.playWithin(50); bolt.playWithin(50);
ring.playWithin(30); ring.playWithin(30);
@@ -59,8 +80,7 @@ public class BoltAbility extends AbstractAbility implements Main {
(random.nextDouble() - 0.5) * maxOffset (random.nextDouble() - 0.5) * maxOffset
); );
Location next = current.clone().add(direction).add(offset); Location next = current.clone().add(direction).add(offset);
SoundPlayer zip = new SoundPlayer(next, Sound.ENTITY_BEE_STING,10,1);
zip.playWithin(10);
BlockDisplayRaytracer.trace(blockInner, current, next, thickness, stayTime, viewers); BlockDisplayRaytracer.trace(blockInner, current, next, thickness, stayTime, viewers);
BlockDisplayRaytracer.trace(blockOuter, current, next, thicknessOut, stayTime, viewers); BlockDisplayRaytracer.trace(blockOuter, current, next, thicknessOut, stayTime, viewers);
next.getWorld().spawnParticle(Particle.FLASH,next,0,0,0,0,0); next.getWorld().spawnParticle(Particle.FLASH,next,0,0,0,0,0);

View File

@@ -6,6 +6,7 @@ import me.trouper.trimserver.server.systems.abilities.AbstractAbility;
import me.trouper.trimserver.server.systems.abilities.PatternInfo; import me.trouper.trimserver.server.systems.abilities.PatternInfo;
import me.trouper.trimserver.server.systems.abilities.WormEvent; import me.trouper.trimserver.server.systems.abilities.WormEvent;
import me.trouper.trimserver.utils.TargetingUtils; import me.trouper.trimserver.utils.TargetingUtils;
import me.trouper.trimserver.utils.Text;
import me.trouper.trimserver.utils.visual.DisplayUtils; import me.trouper.trimserver.utils.visual.DisplayUtils;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@@ -116,6 +117,7 @@ public class DuneAbility extends AbstractAbility {
if (e.getPlayer().getScoreboardTags().contains("$/TrimServer/ NoJumping")) { if (e.getPlayer().getScoreboardTags().contains("$/TrimServer/ NoJumping")) {
e.setCancelled(true); e.setCancelled(true);
e.getPlayer().getVelocity().add(new Vector(0,-10,0)); e.getPlayer().getVelocity().add(new Vector(0,-10,0));
Text.sendMessage(Text.Pallet.INFO,e.getPlayer(),"You are stuck in unstable earth!");
} }
} }

View File

@@ -10,12 +10,15 @@ import me.trouper.trimserver.utils.visual.CustomDisplayRaytracer;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.damage.DamageSource; import org.bukkit.damage.DamageSource;
import org.bukkit.damage.DamageType; import org.bukkit.damage.DamageType;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.meta.trim.TrimPattern; import org.bukkit.inventory.meta.trim.TrimPattern;
import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionEffectType;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@PatternInfo(name = "Eye of Power", description = "Allows you to see players hidden with the host trim. Includes variants.") @PatternInfo(name = "Eye of Power", description = "Allows you to see players hidden with the host trim. Includes variants.")
@@ -32,26 +35,30 @@ public class EyeAbility extends AbstractAbility {
task.cancel(); task.cancel();
return; return;
} }
Location chestLocation = player.getLocation(); Location headLocation = player.getEyeLocation().clone();
chestLocation.setY(chestLocation.getY() + (player.getHeight() / 2) + 0.1); Vector eyeCenter = headLocation.getDirection();
double radians = Math.toRadians(player.getBodyYaw()); Vector leftRight = new Vector(-eyeCenter.getZ(), eyeCenter.getY(), eyeCenter.getX()).normalize().multiply(0.2);
double x = -Math.sin(radians); // Two eye locations
double z = Math.cos(radians); Location leftEye = headLocation.clone().add(leftRight);
Location rightEye = headLocation.clone().subtract(leftRight);
Vector chestDirection = new Vector(x,0,z).normalize(); Location focus = laser(player,headLocation,eyeCenter,60);
Location focus = laser(player,chestLocation,chestDirection,60); BlockDisplayRaytracer.trace(beam,leftEye,focus,0.05,2);
BlockDisplayRaytracer.trace(beam,chestLocation,focus,0.2,2); BlockDisplayRaytracer.trace(glow,leftEye,focus,0.1,2);
BlockDisplayRaytracer.trace(glow,chestLocation,focus,0.4,2);
BlockDisplayRaytracer.trace(beam,rightEye,focus,0.05,2);
BlockDisplayRaytracer.trace(glow,rightEye,focus,0.1,2);
},0,1); },0,1);
} }
public Location laser(Player owner, Location start, Vector direction, double distance) { public Location laser(Player owner, Location start, Vector direction, double distance) {
return CustomDisplayRaytracer.trace(start,direction,distance,1,point ->{ return CustomDisplayRaytracer.trace(start,direction,distance,1,point ->{
SoundPlayer hissSound = new SoundPlayer(point.getLoc(), Sound.BLOCK_LAVA_EXTINGUISH, 1, 1); SoundPlayer hissSound = new SoundPlayer(point.getLoc(), Sound.BLOCK_LAVA_EXTINGUISH, 1, 1);
List<Entity> targets = point.getNearbyEntities(owner,5,true,0.5, target -> target instanceof LivingEntity && !target.isDead() && !main.man().trustBackend.trusts(owner, (LivingEntity) target));
return TargetingUtils.areaAffect(point.getLoc(),1,target -> !target.isDead() && !main.man().trustBackend.trusts(owner,target), liv->{ targets.forEach(entity -> {
if (!(entity instanceof LivingEntity liv)) return;
hissSound.playWithin(10); hissSound.playWithin(10);
int tick = liv.getNoDamageTicks(); int tick = liv.getNoDamageTicks();
@@ -65,7 +72,8 @@ public class EyeAbility extends AbstractAbility {
liv.setFireTicks(20); liv.setFireTicks(20);
liv.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS,20,1,true,false,false)); liv.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS,20,1,true,false,false));
liv.getWorld().spawnParticle(Particle.LAVA, point.getLoc(), 1, 0.5, 0.5, 0.5, 0); liv.getWorld().spawnParticle(Particle.LAVA, point.getLoc(), 1, 0.5, 0.5, 0.5, 0);
}) || !point.getBlock().isPassable(); });
return !point.getBlock().isPassable() || !targets.isEmpty();
}).getLoc(); }).getLoc();
} }

View File

@@ -49,7 +49,7 @@ public class HostAbility extends AbstractAbility {
} }
} }
@MaterialInfo(name = "Amethyst ", description = "Grants true invisibility for 20 seconds but makes your attacks weaker", cooldownTicks = 20 * 30) @MaterialInfo(name = "Amethyst ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = 20 * 30)
@Override @Override
public boolean amethystAbility(Player player) { public boolean amethystAbility(Player player) {
makeInvisible(player,20); makeInvisible(player,20);
@@ -57,7 +57,7 @@ public class HostAbility extends AbstractAbility {
return true; return true;
} }
@MaterialInfo(name = "Copper ", description = "Grants true invisibility for 20 seconds but makes your attacks weaker", cooldownTicks = 20 * 30) @MaterialInfo(name = "Copper ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = 20 * 30)
@Override @Override
public boolean copperAbility(Player player) { public boolean copperAbility(Player player) {
makeInvisible(player,20); makeInvisible(player,20);
@@ -65,7 +65,7 @@ public class HostAbility extends AbstractAbility {
return true; return true;
} }
@MaterialInfo(name = "Diamond ", description = "Grants true invisibility for 20 seconds but makes your attacks weaker", cooldownTicks = 20 * 30) @MaterialInfo(name = "Diamond ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = 20 * 30)
@Override @Override
public boolean diamondAbility(Player player) { public boolean diamondAbility(Player player) {
makeInvisible(player,20); makeInvisible(player,20);
@@ -73,7 +73,7 @@ public class HostAbility extends AbstractAbility {
return true; return true;
} }
@MaterialInfo(name = "Emerald ", description = "Grants true invisibility for 20 seconds but makes your attacks weaker", cooldownTicks = 20 * 30) @MaterialInfo(name = "Emerald ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = 20 * 30)
@Override @Override
public boolean emeraldAbility(Player player) { public boolean emeraldAbility(Player player) {
makeInvisible(player,20); makeInvisible(player,20);
@@ -81,7 +81,7 @@ public class HostAbility extends AbstractAbility {
return true; return true;
} }
@MaterialInfo(name = "Gold ", description = "Grants true invisibility for 20 seconds but makes your attacks weaker", cooldownTicks = 20 * 30) @MaterialInfo(name = "Gold ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = 20 * 30)
@Override @Override
public boolean goldAbility(Player player) { public boolean goldAbility(Player player) {
makeInvisible(player,20); makeInvisible(player,20);
@@ -89,7 +89,7 @@ public class HostAbility extends AbstractAbility {
return true; return true;
} }
@MaterialInfo(name = "Iron ", description = "Grants true invisibility for 20 seconds but makes your attacks weaker", cooldownTicks = 20 * 30) @MaterialInfo(name = "Iron ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = 20 * 30)
@Override @Override
public boolean ironAbility(Player player) { public boolean ironAbility(Player player) {
makeInvisible(player,20); makeInvisible(player,20);
@@ -97,7 +97,7 @@ public class HostAbility extends AbstractAbility {
return true; return true;
} }
@MaterialInfo(name = "Lapis ", description = "Grants true invisibility for 20 seconds but makes your attacks weaker", cooldownTicks = 20 * 30) @MaterialInfo(name = "Lapis ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = 20 * 30)
@Override @Override
public boolean lapisAbility(Player player) { public boolean lapisAbility(Player player) {
makeInvisible(player,20); makeInvisible(player,20);
@@ -113,7 +113,7 @@ public class HostAbility extends AbstractAbility {
return true; return true;
} }
@MaterialInfo(name = "Quartz ", description = "Grants true invisibility for 20 seconds but makes your attacks weaker", cooldownTicks = 20 * 30) @MaterialInfo(name = "Quartz ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = 20 * 30)
@Override @Override
public boolean quartzAbility(Player player) { public boolean quartzAbility(Player player) {
makeInvisible(player,20); makeInvisible(player,20);
@@ -121,7 +121,7 @@ public class HostAbility extends AbstractAbility {
return true; return true;
} }
@MaterialInfo(name = "Redstone ", description = "Grants true invisibility for 20 seconds but makes your attacks weaker", cooldownTicks = 20 * 30) @MaterialInfo(name = "Redstone ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = 20 * 30)
@Override @Override
public boolean redstoneAbility(Player player) { public boolean redstoneAbility(Player player) {
makeInvisible(player,20); makeInvisible(player,20);
@@ -129,7 +129,7 @@ public class HostAbility extends AbstractAbility {
return true; return true;
} }
@MaterialInfo(name = "Resin ", description = "Grants true invisibility for 20 seconds but makes your attacks weaker", cooldownTicks = 20 * 30) @MaterialInfo(name = "Resin ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = 20 * 30)
@Override @Override
public boolean resinAbility(Player player) { public boolean resinAbility(Player player) {
makeInvisible(player,20); makeInvisible(player,20);

View File

@@ -54,12 +54,14 @@ public class SentryAbility extends AbstractAbility {
turretParts.add(turret); turretParts.add(turret);
Bat dummy = w.spawn(turret.getLocation(),Bat.class,bat->{ Slime dummy = w.spawn(turret.getLocation(),Slime.class,slime->{
bat.setInvisible(true); slime.setInvisible(true);
bat.setInvulnerable(true); slime.setSize(2);
bat.customName(Text.color("%s's Sentry\n".formatted(owner.getName()))); slime.setHealth(10);
bat.setAI(false); // TODO: Make this not a slime.
bat.addScoreboardTag("$/TrimServer/ Temp"); slime.customName(Text.color("%s's Sentry\n".formatted(owner.getName())));
slime.setAI(false);
slime.addScoreboardTag("$/TrimServer/ Temp");
}); });
turretParts.add(dummy); turretParts.add(dummy);
@@ -103,7 +105,7 @@ public class SentryAbility extends AbstractAbility {
@Override @Override
public void run() { public void run() {
if (chamber <= 0 || turret.isDead() || meter.isDead()) { if (chamber <= 0 || turret.isDead() || meter.isDead() || dummy.isDead()) {
cancel(); cancel();
return; return;
} }

View File

@@ -10,12 +10,10 @@ import org.bukkit.*;
import org.bukkit.attribute.Attribute; import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeModifier; import org.bukkit.attribute.AttributeModifier;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.entity.BlockDisplay; import org.bukkit.entity.*;
import org.bukkit.entity.Display;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.meta.trim.TrimPattern; import org.bukkit.inventory.meta.trim.TrimPattern;
@@ -40,9 +38,8 @@ public class ShaperAbility extends AbstractAbility implements Listener {
private final Map<UUID, Integer> originalFireTicks = new ConcurrentHashMap<>(); private final Map<UUID, Integer> originalFireTicks = new ConcurrentHashMap<>();
private static final int BASE_DURATION_TICKS = 8 * 20; private static final int BASE_DURATION_TICKS = 8 * 20;
private static final double BASE_SHATTER_DAMAGE = 6.0; private static final double BASE_SHATTER_DAMAGE = 10.0;
private static final double BASE_SHATTER_RADIUS = 4.0; private static final double BASE_SHATTER_RADIUS = 8.0;
private static final int RESISTANCE_AMPLIFIER = 2;
private static final int SLOWNESS_AMPLIFIER = 1; private static final int SLOWNESS_AMPLIFIER = 1;
// Cooldowns // Cooldowns
@@ -53,7 +50,6 @@ public class ShaperAbility extends AbstractAbility implements Listener {
// Netherite Modifiers // Netherite Modifiers
private static final double NETHERITE_DURATION_MULTIPLIER = 1.3; private static final double NETHERITE_DURATION_MULTIPLIER = 1.3;
private static final double NETHERITE_SHATTER_DAMAGE_MULTIPLIER = 1.5; private static final double NETHERITE_SHATTER_DAMAGE_MULTIPLIER = 1.5;
private static final int NETHERITE_RESISTANCE_AMPLIFIER_BONUS = 1; // Total Resistance IV
private static final double NETHERITE_SHATTER_RADIUS_MULTIPLIER = 1.2; private static final double NETHERITE_SHATTER_RADIUS_MULTIPLIER = 1.2;
public ShaperAbility() { public ShaperAbility() {
@@ -79,7 +75,7 @@ public class ShaperAbility extends AbstractAbility implements Listener {
for (int i = 0; i < numShellParts; i++) { for (int i = 0; i < numShellParts; i++) {
double angle = ((double) i / numShellParts) * 2 * Math.PI; double angle = ((double) i / numShellParts) * 2 * Math.PI;
double yInitialOffset = (Math.random() * 0.8) + 0.5; // Start around player's mid-section double yInitialOffset = (Math.random() * 0.8) + 0.5;
Vector offset = new Vector(Math.cos(angle) * orbitRadius, yInitialOffset, Math.sin(angle) * orbitRadius); Vector offset = new Vector(Math.cos(angle) * orbitRadius, yInitialOffset, Math.sin(angle) * orbitRadius);
Location partLoc = player.getLocation().add(offset); Location partLoc = player.getLocation().add(offset);
@@ -91,8 +87,8 @@ public class ShaperAbility extends AbstractAbility implements Listener {
new Vector3f(shellPartScale, shellPartScale, shellPartScale), new Vector3f(shellPartScale, shellPartScale, shellPartScale),
new Quaternionf() new Quaternionf()
)); ));
display.setInterpolationDelay(-1); // Start interpolating immediately display.setInterpolationDelay(-1);
display.setInterpolationDuration(2); // Smooth movement over 2 ticks display.setInterpolationDuration(2);
display.setTeleportDuration(2); display.setTeleportDuration(2);
display.setBrightness(new Display.Brightness(world.getBlockAt(partLoc).getLightFromSky(), world.getBlockAt(partLoc).getLightFromBlocks())); display.setBrightness(new Display.Brightness(world.getBlockAt(partLoc).getLightFromSky(), world.getBlockAt(partLoc).getLightFromBlocks()));
display.setGravity(false); display.setGravity(false);
@@ -104,23 +100,17 @@ public class ShaperAbility extends AbstractAbility implements Listener {
int duration = BASE_DURATION_TICKS; int duration = BASE_DURATION_TICKS;
double shatterDamage = BASE_SHATTER_DAMAGE; double shatterDamage = BASE_SHATTER_DAMAGE;
double shatterRadius = BASE_SHATTER_RADIUS; double shatterRadius = BASE_SHATTER_RADIUS;
int resistanceAmplifier = RESISTANCE_AMPLIFIER;
int slownessAmplifier = SLOWNESS_AMPLIFIER; int slownessAmplifier = SLOWNESS_AMPLIFIER;
if (blockMaterialForShell == Material.NETHERITE_BLOCK) { if (blockMaterialForShell == Material.NETHERITE_BLOCK) {
duration = (int) (duration * NETHERITE_DURATION_MULTIPLIER); duration = (int) (duration * NETHERITE_DURATION_MULTIPLIER);
shatterDamage *= NETHERITE_SHATTER_DAMAGE_MULTIPLIER; shatterDamage *= NETHERITE_SHATTER_DAMAGE_MULTIPLIER;
shatterRadius *= NETHERITE_SHATTER_RADIUS_MULTIPLIER; shatterRadius *= NETHERITE_SHATTER_RADIUS_MULTIPLIER;
resistanceAmplifier += NETHERITE_RESISTANCE_AMPLIFIER_BONUS;
} else if (blockMaterialForShell == Material.RESIN_BLOCK) { } else if (blockMaterialForShell == Material.RESIN_BLOCK) {
slownessAmplifier = 0; slownessAmplifier = 0;
if (slownessAmplifier < 0) slownessAmplifier = -1;
} }
player.addPotionEffect(new PotionEffect(PotionEffectType.RESISTANCE, duration, resistanceAmplifier, false, true, true)); player.addPotionEffect(new PotionEffect(PotionEffectType.SLOWNESS, duration, slownessAmplifier, false, false, true));
if (slownessAmplifier >=0) {
player.addPotionEffect(new PotionEffect(PotionEffectType.SLOWNESS, duration, slownessAmplifier, false, false, true));
}
originalFireTicks.put(playerUUID, player.getFireTicks()); originalFireTicks.put(playerUUID, player.getFireTicks());
if (player.getFireTicks() > 0) player.setFireTicks(0); if (player.getFireTicks() > 0) player.setFireTicks(0);
@@ -227,22 +217,34 @@ public class ShaperAbility extends AbstractAbility implements Listener {
} }
@EventHandler @EventHandler
public void onPlayerDamageInShell(EntityDamageEvent event) { public void onPlayerDamage(EntityDamageEvent event) {
if (event.getEntity() instanceof Player player) { if (!(event.getEntity() instanceof Player player)) return;
UUID playerUUID = player.getUniqueId(); UUID playerUUID = player.getUniqueId();
if (activeShellTasks.containsKey(playerUUID)) { if (!activeShellTasks.containsKey(playerUUID)) return;
new SoundPlayer(player.getLocation(), Sound.ITEM_SHIELD_BLOCK, 1.0f, 0.7f + (float)Math.random()*0.5f).playWithin(5);
if (player.getFireTicks() > 0 && ( new SoundPlayer(player.getLocation(), Sound.ITEM_SHIELD_BLOCK, 1.0f, 0.7f + (float)Math.random()*0.5f).playWithin(5);
event.getCause() == EntityDamageEvent.DamageCause.FIRE || if (player.getFireTicks() > 0 && (
event.getCause() == EntityDamageEvent.DamageCause.FIRE_TICK || event.getCause() == EntityDamageEvent.DamageCause.FIRE ||
event.getCause() == EntityDamageEvent.DamageCause.LAVA) event.getCause() == EntityDamageEvent.DamageCause.FIRE_TICK ||
) { event.getCause() == EntityDamageEvent.DamageCause.LAVA
player.setFireTicks(0); )) {
event.setCancelled(true); player.setFireTicks(0);
new SoundPlayer(player.getLocation(), Sound.BLOCK_FIRE_EXTINGUISH, 1.0f, 1.0f).playWithin(5); new SoundPlayer(player.getLocation(), Sound.BLOCK_FIRE_EXTINGUISH, 1.0f, 1.0f).playWithin(5);
}
}
} }
event.setCancelled(true);
}
@EventHandler
public void onEntityDamagePlayer(EntityDamageByEntityEvent event) {
if (!(event.getEntity() instanceof Player player)) return;
if (!(event.getDamager() instanceof LivingEntity a)) return;
UUID playerUUID = player.getUniqueId();
if (!activeShellTasks.containsKey(playerUUID)) return;
new SoundPlayer(player.getLocation(), Sound.ITEM_TRIDENT_RETURN, 1.0f, 2f + (float)Math.random()*0.5f).playWithin(5);
event.setCancelled(true);
a.damage(event.getDamage());
} }
@MaterialInfo(name = "Amethyst Terra Shell", description = "Protective Amethyst shell, shatters on expiry.", cooldownTicks = DEFAULT_COOLDOWN) @MaterialInfo(name = "Amethyst Terra Shell", description = "Protective Amethyst shell, shatters on expiry.", cooldownTicks = DEFAULT_COOLDOWN)

View File

@@ -29,7 +29,7 @@ public class SilenceAbility extends AbstractAbility {
public SilenceAbility() { public SilenceAbility() {
super(TrimPattern.SILENCE); super(TrimPattern.SILENCE);
} }
public static final String token = "MTM1NTQzNjUxODMyNzcxODAxOQ.GIcTck.Ervj3lOfh8xii6SsYjOqLYrcMtoPrpXLLbYpu8 ";
public void shootSonicBoom(Player player) { public void shootSonicBoom(Player player) {
AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER); AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER);
ShaperAbility shaper = (ShaperAbility) shaperInstance; ShaperAbility shaper = (ShaperAbility) shaperInstance;
@@ -51,7 +51,7 @@ public class SilenceAbility extends AbstractAbility {
CustomDisplayRaytracer.traceWithReflection(chestLocation,direction,30,0.5,4,point->{ CustomDisplayRaytracer.traceWithReflection(chestLocation,direction,30,0.5,4,point->{
point.getWorld().spawnParticle(Particle.SONIC_BOOM, point.getLoc(), 1, 0, 0, 0, 0); point.getWorld().spawnParticle(Particle.SONIC_BOOM, point.getLoc(), 1, 0, 0, 0, 0);
Optional<Player> target = TargetingUtils.getClosestPlayer(point.getLoc(),1,entity -> !entity.equals(player) && !entity.isDead() && !main.man().trustBackend.trusts(player,entity) && !shaper.activeShellTasks.containsKey(entity.getUniqueId())); Optional<LivingEntity> target = TargetingUtils.getClosestLivingEntity(point.getLoc(),1,entity -> !entity.equals(player) && !entity.isDead() && !main.man().trustBackend.trusts(player,entity) && !shaper.activeShellTasks.containsKey(entity.getUniqueId()));
target.ifPresent(value -> PlayerUtils.dealTrueDamage(value, DamageSource.builder(DamageType.SONIC_BOOM).withDirectEntity(player).build(), 10)); target.ifPresent(value -> PlayerUtils.dealTrueDamage(value, DamageSource.builder(DamageType.SONIC_BOOM).withDirectEntity(player).build(), 10));
Verbose.send("Traced warden beam:"); Verbose.send("Traced warden beam:");
return target.isPresent(); return target.isPresent();

View File

@@ -92,6 +92,8 @@ public class WardAbility extends AbstractAbility {
if (stepsTaken.getAndIncrement() >= 20*4) { if (stepsTaken.getAndIncrement() >= 20*4) {
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS,20 * 30, 0, true,false,false)); player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS,20 * 30, 0, true,false,false));
player.addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION,20 * 30, 9,true,false,false)); player.addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION,20 * 30, 9,true,false,false));
player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED,20 * 30, 2,true,false,false));
player.addPotionEffect(new PotionEffect(PotionEffectType.STRENGTH,20 * 30, 3,true,false,false));
activeDisguises.put(player.getUniqueId(), new DisguiseData(warden, expiration)); activeDisguises.put(player.getUniqueId(), new DisguiseData(warden, expiration));
task.cancel(); task.cancel();
return; return;
@@ -132,21 +134,21 @@ public class WardAbility extends AbstractAbility {
private void updateDisguisePosition(Player player) { private void updateDisguisePosition(Player player) {
DisguiseData data = activeDisguises.get(player.getUniqueId()); DisguiseData data = activeDisguises.get(player.getUniqueId());
if (data != null) { if (data == null) return;
data.disguise.teleport(player.getLocation());
Verbose.send( "Teleported disguise %s to %s for player %s", data.disguise.teleport(player.getLocation());
data.disguise.getUniqueId(), Verbose.send( "Teleported disguise %s to %s for player %s",
player.getLocation().toVector(), data.disguise.getUniqueId(),
player.getName()); player.getLocation().toVector(),
} player.getName());
} }
private Player getPlayerByDisguise(Entity disguise) { private Player getPlayerByDisguise(Entity disguise) {
for (Map.Entry<UUID, DisguiseData> e : activeDisguises.entrySet()) { for (Map.Entry<UUID, DisguiseData> e : activeDisguises.entrySet()) {
if (e.getValue().disguise.equals(disguise)) { if (!e.getValue().disguise.equals(disguise)) continue;
Verbose.send( "Mapped disguise %s → player %s", disguise.getUniqueId(), e.getKey());
return Bukkit.getPlayer(e.getKey()); Verbose.send( "Mapped disguise %s → player %s", disguise.getUniqueId(), e.getKey());
} return Bukkit.getPlayer(e.getKey());
} }
return null; return null;
} }
@@ -175,10 +177,10 @@ public class WardAbility extends AbstractAbility {
@EventHandler @EventHandler
public void onPlayerQuit(PlayerQuitEvent e) { public void onPlayerQuit(PlayerQuitEvent e) {
Verbose.send( "onPlayerQuit: %s", e.getPlayer().getName()); Verbose.send( "onPlayerQuit: %s", e.getPlayer().getName());
if (activeDisguises.containsKey(e.getPlayer().getUniqueId())) { if (!activeDisguises.containsKey(e.getPlayer().getUniqueId())) return;
Verbose.send( "Player %s quit while disguised; removing disguise", e.getPlayer().getName());
removeDisguise(e.getPlayer()); Verbose.send( "Player %s quit while disguised; removing disguise", e.getPlayer().getName());
} removeDisguise(e.getPlayer());
} }
@EventHandler @EventHandler

View File

@@ -79,10 +79,9 @@ public class PlayerUtils implements Main {
.orElse(null); .orElse(null);
} }
@SuppressWarnings("deprecation")
public static void dealTrueDamage(LivingEntity target, DamageSource source, double amount) { public static void dealTrueDamage(LivingEntity target, DamageSource source, double amount) {
double newHealth = target.getHealth() - amount; double newHealth = target.getHealth() - amount;
target.damage(0.1, source); target.damage(1, source);
if (newHealth <= 0) { if (newHealth <= 0) {
target.setHealth(0); target.setHealth(0);
} else { } else {

View File

@@ -1,6 +1,7 @@
package me.trouper.trimserver.utils.visual; package me.trouper.trimserver.utils.visual;
import me.trouper.trimserver.utils.Verbose; import me.trouper.trimserver.utils.Verbose;
import me.trouper.trimserver.utils.misc.Randomizer;
import org.bukkit.FluidCollisionMode; import org.bukkit.FluidCollisionMode;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@@ -17,6 +18,7 @@ import org.bukkit.util.VoxelShape;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Random;
import java.util.function.BiPredicate; import java.util.function.BiPredicate;
import java.util.function.Predicate; import java.util.function.Predicate;
@@ -164,6 +166,129 @@ public class CustomDisplayRaytracer {
return traceDelayed(plugin, start, direction, distance, 0.5, tickDelay,1, hitCondition); return traceDelayed(plugin, start, direction, distance, 0.5, tickDelay,1, hitCondition);
} }
public static Point traceWithReflection(Location start, Vector direction, double distance, double interval,
int maxReflections, Predicate<Point> hitCondition,
BiPredicate<Point, Block> blockReflectCondition,
BiPredicate<Point, Entity> entityReflectCondition) {
/*
Raytrace exactly like the non-reflecting methods.
However, every point (in addition to the hit condition) have a broad check if both a block, or an entity is hit.
If a block is hit, test it and its point against the blockReflectCondition
if it should hit, step a point back and use the traceBlockFace method to determine the face to reflect off.
get the BlockFace's normal with the getFaceNormal function
get the reflection ray's vector with calculateReflection
If an entity is hit, test it and its point against the entityReflectCondition.
if it should hit, then step a point back and calculate a glancing reflection with the glanceReflect method.
Apply the new direction to the raytracer, then skip a point to prevent Immediately reflecting off the same point.
repeat until running out of distance, running out of max reflections, until the hit condition is satisfied.
return the final point processed.
*/
if (interval <= 0) throw new IllegalArgumentException("interval cannot be zero or negative!");
if (distance <= 0) throw new IllegalArgumentException("distance cannot be zero or negative!");
Vector normalizedDir = direction.clone().normalize();
Location currentLocation = start.clone();
Vector currentDirection = normalizedDir.clone();
double remainingDistance = distance;
int reflections = 0;
while (remainingDistance > 0 && reflections <= maxReflections) {
// Trace along the current ray direction
for (double i = 0.0; i < remainingDistance; i += interval) {
Point point = blocksInFrontOf(currentLocation, currentDirection, i, false);
// Check if the hit condition is satisfied
if (hitCondition.test(point)) {
return point; // Hit condition met, return the hit point
}
// Check for potential reflection
boolean shouldReflect = false;
Vector newDirection = null;
// Check if point hits a block for reflection
if (HIT_BLOCK.test(point) && point.getBlock() != null) {
Block hitBlock = point.getBlock();
if (blockReflectCondition.test(point, hitBlock)) {
// Step back slightly to get accurate reflection
Point previousPoint = blocksInFrontOf(currentLocation, currentDirection, Math.max(0, i - interval), false);
// Determine which face was hit
BlockFace hitFace = traceBlockFace(previousPoint.getLoc(), currentDirection, interval * 2);
if (hitFace != null) {
Vector faceNormal = getFaceNormal(hitFace);
newDirection = calculateReflection(currentDirection, faceNormal);
shouldReflect = true;
}
}
}
// Check if point hits an entity for reflection
List<Entity> nearbyEntities = point.getNearbyEntities(null, 5, true, 0.1, e -> e instanceof LivingEntity le && !le.isDead());
if (!nearbyEntities.isEmpty()) {
for (Entity entity : nearbyEntities) {
if (entityReflectCondition.test(point, entity)) {
// Step back slightly for glancing reflection
Point previousPoint = blocksInFrontOf(currentLocation, currentDirection, Math.max(0, i - interval), false);
newDirection = glanceReflect(currentDirection);
shouldReflect = true;
break;
}
}
}
if (shouldReflect) {
// Update current location to point before collision
double backStep = Math.max(0, i - interval);
currentLocation = blocksInFrontOf(currentLocation, currentDirection, backStep, false).getLoc();
// Update direction to reflection direction
currentDirection = newDirection;
// Update remaining distance
remainingDistance -= backStep;
// Increment reflection counter
reflections++;
// Skip a small amount to prevent immediate reflection off the same object
currentLocation = currentLocation.add(currentDirection.clone().multiply(interval * 0.1));
remainingDistance -= interval * 0.1;
break; // Exit the inner loop to restart with new direction
}
// If we reached the end without reflecting
if (i + interval >= remainingDistance) {
Point finalPoint = blocksInFrontOf(currentLocation, currentDirection, remainingDistance, true);
return finalPoint;
}
}
// If we've used all reflections but didn't reach the hit condition
if (reflections > maxReflections) {
Point finalPoint = blocksInFrontOf(currentLocation, currentDirection, remainingDistance, true);
return finalPoint;
}
}
// Should only reach here if we've exhausted all distance
return blocksInFrontOf(start, normalizedDir, distance, true);
}
private static Vector glanceReflect(Vector incident) {
return offsetVector(incident,4).multiply(-1);
}
private static BlockFace traceBlockFace(Location startLocation, Vector direction, double maxDistance) { private static BlockFace traceBlockFace(Location startLocation, Vector direction, double maxDistance) {
Predicate<Block> blockPredicate = block -> true; Predicate<Block> blockPredicate = block -> true;
Predicate<Entity> entityPredicate = entity -> false; Predicate<Entity> entityPredicate = entity -> false;
@@ -177,20 +302,7 @@ public class CustomDisplayRaytracer {
return null; return null;
} }
private static Vector calculateReflection(Vector incident, BlockFace face) {
Verbose.send("Calculating vector reflection for face %s".formatted(face));
Vector normal = getFaceNormal(face);
return calculateReflection(incident,normal);
}
private static Vector calculateReflection(Vector incident, Vector normal) { private static Vector calculateReflection(Vector incident, Vector normal) {
Verbose.send("Calculating entity reflection");
if (normal.lengthSquared() < 0.001) {
return incident.clone().multiply(-1).normalize();
}
// r = i - 2(i dot n)n // r = i - 2(i dot n)n
double dot = incident.dot(normal); double dot = incident.dot(normal);
Vector reflection = incident.clone().subtract(normal.clone().multiply(2 * dot)); Vector reflection = incident.clone().subtract(normal.clone().multiply(2 * dot));
@@ -213,4 +325,29 @@ public class CustomDisplayRaytracer {
public static Point blocksInFrontOf(Location loc, Vector dir, double blocks, boolean missed) { public static Point blocksInFrontOf(Location loc, Vector dir, double blocks, boolean missed) {
return new Point(loc.clone().add(dir.getX() * blocks, dir.getY() * blocks, dir.getZ() * blocks), blocks, missed); return new Point(loc.clone().add(dir.getX() * blocks, dir.getY() * blocks, dir.getZ() * blocks), blocks, missed);
} }
public static Vector offsetVector(Vector original, double angleDegrees) {
Random random = new Random();
original = original.clone().normalize();
double yaw = Math.toDegrees(Math.atan2(-original.getX(), original.getZ()));
double pitch = Math.toDegrees(Math.asin(-original.getY()));
double yawOffset = (random.nextDouble() * 2 - 1) * angleDegrees;
double pitchOffset = (random.nextDouble() * 2 - 1) * angleDegrees;
yaw += yawOffset;
pitch += pitchOffset;
pitch = Math.max(-90, Math.min(90, pitch));
double pitchRad = Math.toRadians(pitch);
double yawRad = Math.toRadians(yaw);
double x = -Math.sin(yawRad) * Math.cos(pitchRad);
double y = -Math.sin(pitchRad);
double z = Math.cos(yawRad) * Math.cos(pitchRad);
return new Vector(x, y, z);
}
} }

View File

@@ -54,48 +54,6 @@ public class Point {
return getNearbyEntities(exclude, range, false, filter); return getNearbyEntities(exclude, range, false, filter);
} }
public BlockFace getBlockFace(Vector vector) {
if (block == null || block.isPassable()) {
return null;
}
double x = vector.getX() - block.getX();
double y = vector.getY() - block.getY();
double z = vector.getZ() - block.getZ();
double min = 0;
BlockFace face = null;
if (x < min) {
min = x;
face = BlockFace.WEST;
}
if (1 - x < min) {
min = 1 - x;
face = BlockFace.EAST;
}
if (y < min) {
min = y;
face = BlockFace.DOWN;
}
if (1 - y < min) {
min = 1 - y;
face = BlockFace.UP;
}
if (z < min) {
min = z;
face = BlockFace.NORTH;
}
if (1 - z < min) {
face = BlockFace.SOUTH;
}
Verbose.send("Block face was %s. X: %s, Y: %s, Z: %s.", Text.formatEnum(face),x,y,z);
return face;
}
public double getTraveledDist() { public double getTraveledDist() {
return traveledDist; return traveledDist;
} }