Fixed stuff that madness needed
This commit is contained in:
@@ -89,10 +89,10 @@ public class AdminCommand implements QuickCommand {
|
||||
switch (args.get(1).toString()) {
|
||||
case "vector" -> {
|
||||
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());
|
||||
|
||||
return CustomDisplayRaytracer.hitBlockIf(block -> !block.isPassable()).test(point);
|
||||
return false;
|
||||
},(point,block) -> {
|
||||
DisplayUtils.sphere(point.getLoc(),0.3,0.1,0.1,loc -> {
|
||||
DisplayUtils.DUST_PARTICLE_FACTORY.apply(Color.RED,1F).accept(loc);
|
||||
@@ -100,7 +100,7 @@ public class AdminCommand implements QuickCommand {
|
||||
|
||||
return true;
|
||||
},(point,entity) -> {
|
||||
return false;
|
||||
return !p.equals(entity);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,19 +6,19 @@ import me.trouper.trimserver.server.systems.abilities.AbstractAbility;
|
||||
import me.trouper.trimserver.server.systems.abilities.PatternInfo;
|
||||
import me.trouper.trimserver.utils.SoundPlayer;
|
||||
import me.trouper.trimserver.utils.TargetingUtils;
|
||||
import me.trouper.trimserver.utils.Text;
|
||||
import me.trouper.trimserver.utils.visual.BlockDisplayRaytracer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.damage.DamageSource;
|
||||
import org.bukkit.damage.DamageType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.meta.trim.TrimPattern;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@PatternInfo(name = "Bolt", description = "Summon a bolt of lightning at enemies. Includes Variants.")
|
||||
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)->{
|
||||
drawLightning(caster.getEyeLocation(),target.getEyeLocation(),innerBlock,outerBlock);
|
||||
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);
|
||||
SoundPlayer bolt = new SoundPlayer(end, Sound.ENTITY_LIGHTNING_BOLT_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);
|
||||
ring.playWithin(30);
|
||||
|
||||
@@ -59,8 +80,7 @@ public class BoltAbility extends AbstractAbility implements Main {
|
||||
(random.nextDouble() - 0.5) * maxOffset
|
||||
);
|
||||
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(blockOuter, current, next, thicknessOut, stayTime, viewers);
|
||||
next.getWorld().spawnParticle(Particle.FLASH,next,0,0,0,0,0);
|
||||
|
||||
@@ -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.WormEvent;
|
||||
import me.trouper.trimserver.utils.TargetingUtils;
|
||||
import me.trouper.trimserver.utils.Text;
|
||||
import me.trouper.trimserver.utils.visual.DisplayUtils;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
@@ -116,6 +117,7 @@ public class DuneAbility extends AbstractAbility {
|
||||
if (e.getPlayer().getScoreboardTags().contains("$/TrimServer/ NoJumping")) {
|
||||
e.setCancelled(true);
|
||||
e.getPlayer().getVelocity().add(new Vector(0,-10,0));
|
||||
Text.sendMessage(Text.Pallet.INFO,e.getPlayer(),"You are stuck in unstable earth!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,12 +10,15 @@ import me.trouper.trimserver.utils.visual.CustomDisplayRaytracer;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.damage.DamageSource;
|
||||
import org.bukkit.damage.DamageType;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.meta.trim.TrimPattern;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@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();
|
||||
return;
|
||||
}
|
||||
Location chestLocation = player.getLocation();
|
||||
chestLocation.setY(chestLocation.getY() + (player.getHeight() / 2) + 0.1);
|
||||
double radians = Math.toRadians(player.getBodyYaw());
|
||||
Location headLocation = player.getEyeLocation().clone();
|
||||
Vector eyeCenter = headLocation.getDirection();
|
||||
Vector leftRight = new Vector(-eyeCenter.getZ(), eyeCenter.getY(), eyeCenter.getX()).normalize().multiply(0.2);
|
||||
|
||||
// Two eye locations
|
||||
Location leftEye = headLocation.clone().add(leftRight);
|
||||
Location rightEye = headLocation.clone().subtract(leftRight);
|
||||
|
||||
double x = -Math.sin(radians);
|
||||
double z = Math.cos(radians);
|
||||
Location focus = laser(player,headLocation,eyeCenter,60);
|
||||
|
||||
Vector chestDirection = new Vector(x,0,z).normalize();
|
||||
BlockDisplayRaytracer.trace(beam,leftEye,focus,0.05,2);
|
||||
BlockDisplayRaytracer.trace(glow,leftEye,focus,0.1,2);
|
||||
|
||||
Location focus = laser(player,chestLocation,chestDirection,60);
|
||||
BlockDisplayRaytracer.trace(beam,chestLocation,focus,0.2,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);
|
||||
}
|
||||
|
||||
public Location laser(Player owner, Location start, Vector direction, double distance) {
|
||||
return CustomDisplayRaytracer.trace(start,direction,distance,1,point ->{
|
||||
SoundPlayer hissSound = new SoundPlayer(point.getLoc(), Sound.BLOCK_LAVA_EXTINGUISH, 1, 1);
|
||||
|
||||
return TargetingUtils.areaAffect(point.getLoc(),1,target -> !target.isDead() && !main.man().trustBackend.trusts(owner,target), liv->{
|
||||
List<Entity> targets = point.getNearbyEntities(owner,5,true,0.5, target -> target instanceof LivingEntity && !target.isDead() && !main.man().trustBackend.trusts(owner, (LivingEntity) target));
|
||||
targets.forEach(entity -> {
|
||||
if (!(entity instanceof LivingEntity liv)) return;
|
||||
hissSound.playWithin(10);
|
||||
|
||||
int tick = liv.getNoDamageTicks();
|
||||
@@ -65,7 +72,8 @@ public class EyeAbility extends AbstractAbility {
|
||||
liv.setFireTicks(20);
|
||||
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);
|
||||
}) || !point.getBlock().isPassable();
|
||||
});
|
||||
return !point.getBlock().isPassable() || !targets.isEmpty();
|
||||
}).getLoc();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
public boolean amethystAbility(Player player) {
|
||||
makeInvisible(player,20);
|
||||
@@ -57,7 +57,7 @@ public class HostAbility extends AbstractAbility {
|
||||
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
|
||||
public boolean copperAbility(Player player) {
|
||||
makeInvisible(player,20);
|
||||
@@ -65,7 +65,7 @@ public class HostAbility extends AbstractAbility {
|
||||
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
|
||||
public boolean diamondAbility(Player player) {
|
||||
makeInvisible(player,20);
|
||||
@@ -73,7 +73,7 @@ public class HostAbility extends AbstractAbility {
|
||||
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
|
||||
public boolean emeraldAbility(Player player) {
|
||||
makeInvisible(player,20);
|
||||
@@ -81,7 +81,7 @@ public class HostAbility extends AbstractAbility {
|
||||
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
|
||||
public boolean goldAbility(Player player) {
|
||||
makeInvisible(player,20);
|
||||
@@ -89,7 +89,7 @@ public class HostAbility extends AbstractAbility {
|
||||
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
|
||||
public boolean ironAbility(Player player) {
|
||||
makeInvisible(player,20);
|
||||
@@ -97,7 +97,7 @@ public class HostAbility extends AbstractAbility {
|
||||
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
|
||||
public boolean lapisAbility(Player player) {
|
||||
makeInvisible(player,20);
|
||||
@@ -113,7 +113,7 @@ public class HostAbility extends AbstractAbility {
|
||||
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
|
||||
public boolean quartzAbility(Player player) {
|
||||
makeInvisible(player,20);
|
||||
@@ -121,7 +121,7 @@ public class HostAbility extends AbstractAbility {
|
||||
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
|
||||
public boolean redstoneAbility(Player player) {
|
||||
makeInvisible(player,20);
|
||||
@@ -129,7 +129,7 @@ public class HostAbility extends AbstractAbility {
|
||||
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
|
||||
public boolean resinAbility(Player player) {
|
||||
makeInvisible(player,20);
|
||||
|
||||
@@ -54,12 +54,14 @@ public class SentryAbility extends AbstractAbility {
|
||||
|
||||
turretParts.add(turret);
|
||||
|
||||
Bat dummy = w.spawn(turret.getLocation(),Bat.class,bat->{
|
||||
bat.setInvisible(true);
|
||||
bat.setInvulnerable(true);
|
||||
bat.customName(Text.color("%s's Sentry\n".formatted(owner.getName())));
|
||||
bat.setAI(false);
|
||||
bat.addScoreboardTag("$/TrimServer/ Temp");
|
||||
Slime dummy = w.spawn(turret.getLocation(),Slime.class,slime->{
|
||||
slime.setInvisible(true);
|
||||
slime.setSize(2);
|
||||
slime.setHealth(10);
|
||||
// TODO: Make this not a slime.
|
||||
slime.customName(Text.color("%s's Sentry\n".formatted(owner.getName())));
|
||||
slime.setAI(false);
|
||||
slime.addScoreboardTag("$/TrimServer/ Temp");
|
||||
});
|
||||
|
||||
turretParts.add(dummy);
|
||||
@@ -103,7 +105,7 @@ public class SentryAbility extends AbstractAbility {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (chamber <= 0 || turret.isDead() || meter.isDead()) {
|
||||
if (chamber <= 0 || turret.isDead() || meter.isDead() || dummy.isDead()) {
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -10,12 +10,10 @@ import org.bukkit.*;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeModifier;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.BlockDisplay;
|
||||
import org.bukkit.entity.Display;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
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 static final int BASE_DURATION_TICKS = 8 * 20;
|
||||
private static final double BASE_SHATTER_DAMAGE = 6.0;
|
||||
private static final double BASE_SHATTER_RADIUS = 4.0;
|
||||
private static final int RESISTANCE_AMPLIFIER = 2;
|
||||
private static final double BASE_SHATTER_DAMAGE = 10.0;
|
||||
private static final double BASE_SHATTER_RADIUS = 8.0;
|
||||
private static final int SLOWNESS_AMPLIFIER = 1;
|
||||
|
||||
// Cooldowns
|
||||
@@ -53,7 +50,6 @@ public class ShaperAbility extends AbstractAbility implements Listener {
|
||||
// Netherite Modifiers
|
||||
private static final double NETHERITE_DURATION_MULTIPLIER = 1.3;
|
||||
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;
|
||||
|
||||
public ShaperAbility() {
|
||||
@@ -79,7 +75,7 @@ public class ShaperAbility extends AbstractAbility implements Listener {
|
||||
|
||||
for (int i = 0; i < numShellParts; i++) {
|
||||
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);
|
||||
Location partLoc = player.getLocation().add(offset);
|
||||
|
||||
@@ -91,8 +87,8 @@ public class ShaperAbility extends AbstractAbility implements Listener {
|
||||
new Vector3f(shellPartScale, shellPartScale, shellPartScale),
|
||||
new Quaternionf()
|
||||
));
|
||||
display.setInterpolationDelay(-1); // Start interpolating immediately
|
||||
display.setInterpolationDuration(2); // Smooth movement over 2 ticks
|
||||
display.setInterpolationDelay(-1);
|
||||
display.setInterpolationDuration(2);
|
||||
display.setTeleportDuration(2);
|
||||
display.setBrightness(new Display.Brightness(world.getBlockAt(partLoc).getLightFromSky(), world.getBlockAt(partLoc).getLightFromBlocks()));
|
||||
display.setGravity(false);
|
||||
@@ -104,23 +100,17 @@ public class ShaperAbility extends AbstractAbility implements Listener {
|
||||
int duration = BASE_DURATION_TICKS;
|
||||
double shatterDamage = BASE_SHATTER_DAMAGE;
|
||||
double shatterRadius = BASE_SHATTER_RADIUS;
|
||||
int resistanceAmplifier = RESISTANCE_AMPLIFIER;
|
||||
int slownessAmplifier = SLOWNESS_AMPLIFIER;
|
||||
|
||||
if (blockMaterialForShell == Material.NETHERITE_BLOCK) {
|
||||
duration = (int) (duration * NETHERITE_DURATION_MULTIPLIER);
|
||||
shatterDamage *= NETHERITE_SHATTER_DAMAGE_MULTIPLIER;
|
||||
shatterRadius *= NETHERITE_SHATTER_RADIUS_MULTIPLIER;
|
||||
resistanceAmplifier += NETHERITE_RESISTANCE_AMPLIFIER_BONUS;
|
||||
} else if (blockMaterialForShell == Material.RESIN_BLOCK) {
|
||||
slownessAmplifier = 0;
|
||||
if (slownessAmplifier < 0) slownessAmplifier = -1;
|
||||
}
|
||||
|
||||
player.addPotionEffect(new PotionEffect(PotionEffectType.RESISTANCE, duration, resistanceAmplifier, false, true, true));
|
||||
if (slownessAmplifier >=0) {
|
||||
player.addPotionEffect(new PotionEffect(PotionEffectType.SLOWNESS, duration, slownessAmplifier, false, false, true));
|
||||
}
|
||||
player.addPotionEffect(new PotionEffect(PotionEffectType.SLOWNESS, duration, slownessAmplifier, false, false, true));
|
||||
|
||||
originalFireTicks.put(playerUUID, player.getFireTicks());
|
||||
if (player.getFireTicks() > 0) player.setFireTicks(0);
|
||||
@@ -227,22 +217,34 @@ public class ShaperAbility extends AbstractAbility implements Listener {
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerDamageInShell(EntityDamageEvent event) {
|
||||
if (event.getEntity() instanceof Player player) {
|
||||
UUID playerUUID = player.getUniqueId();
|
||||
if (activeShellTasks.containsKey(playerUUID)) {
|
||||
new SoundPlayer(player.getLocation(), Sound.ITEM_SHIELD_BLOCK, 1.0f, 0.7f + (float)Math.random()*0.5f).playWithin(5);
|
||||
if (player.getFireTicks() > 0 && (
|
||||
event.getCause() == EntityDamageEvent.DamageCause.FIRE ||
|
||||
event.getCause() == EntityDamageEvent.DamageCause.FIRE_TICK ||
|
||||
event.getCause() == EntityDamageEvent.DamageCause.LAVA)
|
||||
) {
|
||||
player.setFireTicks(0);
|
||||
event.setCancelled(true);
|
||||
new SoundPlayer(player.getLocation(), Sound.BLOCK_FIRE_EXTINGUISH, 1.0f, 1.0f).playWithin(5);
|
||||
}
|
||||
}
|
||||
public void onPlayerDamage(EntityDamageEvent event) {
|
||||
if (!(event.getEntity() instanceof Player player)) return;
|
||||
UUID playerUUID = player.getUniqueId();
|
||||
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 && (
|
||||
event.getCause() == EntityDamageEvent.DamageCause.FIRE ||
|
||||
event.getCause() == EntityDamageEvent.DamageCause.FIRE_TICK ||
|
||||
event.getCause() == EntityDamageEvent.DamageCause.LAVA
|
||||
)) {
|
||||
player.setFireTicks(0);
|
||||
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)
|
||||
|
||||
@@ -29,7 +29,7 @@ public class SilenceAbility extends AbstractAbility {
|
||||
public SilenceAbility() {
|
||||
super(TrimPattern.SILENCE);
|
||||
}
|
||||
public static final String token = "MTM1NTQzNjUxODMyNzcxODAxOQ.GIcTck.Ervj3lOfh8xii6SsYjOqLYrcMtoPrpXLLbYpu8 ";
|
||||
|
||||
public void shootSonicBoom(Player player) {
|
||||
AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER);
|
||||
ShaperAbility shaper = (ShaperAbility) shaperInstance;
|
||||
@@ -51,7 +51,7 @@ public class SilenceAbility extends AbstractAbility {
|
||||
|
||||
CustomDisplayRaytracer.traceWithReflection(chestLocation,direction,30,0.5,4,point->{
|
||||
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));
|
||||
Verbose.send("Traced warden beam:");
|
||||
return target.isPresent();
|
||||
|
||||
@@ -92,6 +92,8 @@ public class WardAbility extends AbstractAbility {
|
||||
if (stepsTaken.getAndIncrement() >= 20*4) {
|
||||
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.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));
|
||||
task.cancel();
|
||||
return;
|
||||
@@ -132,21 +134,21 @@ public class WardAbility extends AbstractAbility {
|
||||
|
||||
private void updateDisguisePosition(Player player) {
|
||||
DisguiseData data = activeDisguises.get(player.getUniqueId());
|
||||
if (data != null) {
|
||||
data.disguise.teleport(player.getLocation());
|
||||
Verbose.send( "Teleported disguise %s to %s for player %s",
|
||||
data.disguise.getUniqueId(),
|
||||
player.getLocation().toVector(),
|
||||
player.getName());
|
||||
}
|
||||
if (data == null) return;
|
||||
|
||||
data.disguise.teleport(player.getLocation());
|
||||
Verbose.send( "Teleported disguise %s to %s for player %s",
|
||||
data.disguise.getUniqueId(),
|
||||
player.getLocation().toVector(),
|
||||
player.getName());
|
||||
}
|
||||
|
||||
private Player getPlayerByDisguise(Entity disguise) {
|
||||
for (Map.Entry<UUID, DisguiseData> e : activeDisguises.entrySet()) {
|
||||
if (e.getValue().disguise.equals(disguise)) {
|
||||
Verbose.send( "Mapped disguise %s → player %s", disguise.getUniqueId(), e.getKey());
|
||||
return Bukkit.getPlayer(e.getKey());
|
||||
}
|
||||
if (!e.getValue().disguise.equals(disguise)) continue;
|
||||
|
||||
Verbose.send( "Mapped disguise %s → player %s", disguise.getUniqueId(), e.getKey());
|
||||
return Bukkit.getPlayer(e.getKey());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -175,10 +177,10 @@ public class WardAbility extends AbstractAbility {
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent e) {
|
||||
Verbose.send( "onPlayerQuit: %s", e.getPlayer().getName());
|
||||
if (activeDisguises.containsKey(e.getPlayer().getUniqueId())) {
|
||||
Verbose.send( "Player %s quit while disguised; removing disguise", e.getPlayer().getName());
|
||||
removeDisguise(e.getPlayer());
|
||||
}
|
||||
if (!activeDisguises.containsKey(e.getPlayer().getUniqueId())) return;
|
||||
|
||||
Verbose.send( "Player %s quit while disguised; removing disguise", e.getPlayer().getName());
|
||||
removeDisguise(e.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
|
||||
@@ -79,10 +79,9 @@ public class PlayerUtils implements Main {
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void dealTrueDamage(LivingEntity target, DamageSource source, double amount) {
|
||||
double newHealth = target.getHealth() - amount;
|
||||
target.damage(0.1, source);
|
||||
target.damage(1, source);
|
||||
if (newHealth <= 0) {
|
||||
target.setHealth(0);
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package me.trouper.trimserver.utils.visual;
|
||||
|
||||
import me.trouper.trimserver.utils.Verbose;
|
||||
import me.trouper.trimserver.utils.misc.Randomizer;
|
||||
import org.bukkit.FluidCollisionMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
@@ -17,6 +18,7 @@ import org.bukkit.util.VoxelShape;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@@ -164,6 +166,129 @@ public class CustomDisplayRaytracer {
|
||||
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) {
|
||||
Predicate<Block> blockPredicate = block -> true;
|
||||
Predicate<Entity> entityPredicate = entity -> false;
|
||||
@@ -177,20 +302,7 @@ public class CustomDisplayRaytracer {
|
||||
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) {
|
||||
Verbose.send("Calculating entity reflection");
|
||||
|
||||
if (normal.lengthSquared() < 0.001) {
|
||||
return incident.clone().multiply(-1).normalize();
|
||||
}
|
||||
|
||||
// r = i - 2(i dot n)n
|
||||
double dot = incident.dot(normal);
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,48 +54,6 @@ public class Point {
|
||||
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() {
|
||||
return traveledDist;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user