Подписывайтесь на наш Telegram и не пропускайте важные новости! Перейти

Часть функционала CrystalAura | EvaWare v3 | TH edt.

Начинающий
Начинающий
Статус
Онлайн
Регистрация
26 Янв 2025
Сообщения
33
Реакции
1
Выберите загрузчик игры
  1. Fabric
Привет югейм, хочу слить для вас кристалл ауру которая будет воркать как и на hvh, так и на grimac и других.
Данная аура была перенесена своими руками с thunderHack, прошу не бросаться говном потому-что это мой первый код (рукописный).
чуть чуть подредактил по себя + убрал лишние сеттинги которые пока-что не нужны.


В каких-то случаях может быть гпт, рендер я делал через гпт.

DW: ниже
Пожалуйста, авторизуйтесь для просмотра ссылки.

там я уже пофиксил под грим и т.д, на crystalpvp.cc и lonygrief обходит отлично
 

Вложения

Привет югейм, хочу слить для вас кристалл ауру которая будет воркать как и на hvh, так и на grimac и других.
Данная аура была перенесена своими руками с thunderHack, прошу не бросаться говном потому-что это мой первый код (рукописный).
чуть чуть подредактил по себя + убрал лишние сеттинги которые пока-что не нужны.


В каких-то случаях может быть гпт, рендер я делал через гпт.

DW: ниже
Пожалуйста, авторизуйтесь для просмотра ссылки.

там я уже пофиксил под грим и т.д, на crystalpvp.cc и lonygrief обходит отлично
почему у тебя на заднем фоне фитиль горит
 
ExplosionUtility:
Expand Collapse Copy
package sweetie.evaware.api.utils.world;

import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.component.type.ItemEnchantmentsComponent;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.DamageUtil;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.Difficulty;
import net.minecraft.world.RaycastContext;
import net.minecraft.world.World;
import net.minecraft.world.explosion.Explosion;
import org.apache.commons.lang3.mutable.MutableInt;
import org.jetbrains.annotations.Nullable;
import sweetie.evaware.api.system.interfaces.QuickImports;
import sweetie.evaware.api.utils.math.PredictUtility;

import java.util.Objects;

public final class ExplosionUtility implements QuickImports {

    public static boolean terrainIgnore = false;
    public static boolean assumeBestArmor = false;
    public static Explosion explosion;

    private ExplosionUtility() {
    }

    /**
     * Calculate target damage based on crystal position and target. Uses AutoCrystal settings so use only in AutoCrystal.
     *
     * @param crystalPos the position of the crystal whose damage is to be calculated
     * @param target the damage will be calculated on this entity
     * @param optimized use light calculate
     * @return damage value in Float format
     */
    public static float getAutoCrystalDamage(Vec3d crystalPos, PlayerEntity target, int predictTicks, boolean optimized) {
        if (predictTicks == 0) {
            return getExplosionDamage(crystalPos, target, optimized);
        }
        return getExplosionDamageWPredict(crystalPos, target, PredictUtility.predictBox(target, predictTicks), optimized);
    }

    /**
     * Calculate self damage based on crystal position and self extrapolation (predict).
     *
     * @param explosionPos the position of the explosion whose damage is to be calculated
     * @param predictTicks the number of game ticks for which the player's position should be predicted
     * @param optimized use light calculate
     * @return damage value in Float format
     */
    public static float getSelfExplosionDamage(Vec3d explosionPos, int predictTicks, boolean optimized) {
        return getAutoCrystalDamage(explosionPos, mc.player, predictTicks, optimized);
    }

    /**
     * Calculate target damage based on crystal position and target.
     *
     * @param explosionPos the position of the explosion whose damage is to be calculated
     * @param target the damage will be calculated on this entity
     * @param optimized use light calculate
     * @return damage value in Float format
     */
    public static float getExplosionDamage(Vec3d explosionPos, PlayerEntity target, boolean optimized) {
        if (mc.world == null || mc.player == null || mc.world.getDifficulty() == Difficulty.PEACEFUL || target == null) {
            return 0f;
        }

        MutableExplosion mutableExplosion = getMutableExplosion(explosionPos);
        DamageSource damageSource = Explosion.createDamageSource(mc.world, mc.player);

        if (!new Box(
                MathHelper.floor(explosionPos.x - 11),
                MathHelper.floor(explosionPos.y - 11),
                MathHelper.floor(explosionPos.z - 11),
                MathHelper.floor(explosionPos.x + 13),
                MathHelper.floor(explosionPos.y + 13),
                MathHelper.floor(explosionPos.z + 13)
        ).intersects(target.getBoundingBox())) {
            return 0f;
        }

        if (!target.isImmuneToExplosion(mutableExplosion) && !target.isInvulnerable()) {
            double distExposure = target.squaredDistanceTo(explosionPos) / 144.0;
            if (distExposure <= 1.0) {
                terrainIgnore = resolveIgnoreTerrain();
                double exposure = getExposure(explosionPos, target.getBoundingBox(), optimized);
                terrainIgnore = false;
                double finalExposure = (1.0 - distExposure) * exposure;

                float toDamage = (float) Math.floor((finalExposure * finalExposure + finalExposure) / 2.0 * 7.0 * 12.0 + 1.0);

                if (mc.world.getDifficulty() == Difficulty.EASY) {
                    toDamage = Math.min(toDamage / 2f + 1f, toDamage);
                } else if (mc.world.getDifficulty() == Difficulty.HARD) {
                    toDamage = toDamage * 3f / 2f;
                }

                toDamage = DamageUtil.getDamageLeft(
                        target,
                        toDamage,
                        damageSource,
                        target.getArmor(),
                        (float) Objects.requireNonNull(target.getAttributeInstance(EntityAttributes.ARMOR_TOUGHNESS)).getValue()
                );

                if (target.hasStatusEffect(StatusEffects.RESISTANCE)) {
                    int resistance = 25 - (Objects.requireNonNull(target.getStatusEffect(StatusEffects.RESISTANCE)).getAmplifier() + 1) * 5;
                    float resistanceScaled = toDamage * resistance;
                    toDamage = Math.max(resistanceScaled / 25f, 0f);
                }

                if (toDamage <= 0f) {
                    toDamage = 0f;
                } else {
                    float protAmount = resolveAssumeBestArmor() ? 32f : getProtectionAmount(target.getArmorItems());
                    if (protAmount > 0) {
                        toDamage = DamageUtil.getInflictedDamage(toDamage, protAmount);
                    }
                }

                return toDamage;
            }
        }
        return 0f;
    }

    /**
     * Calculate target damage based on crystal position, target and predicted copy of target.
     *
     * @param explosionPos the position of the explosion whose damage is to be calculated
     * @param target the damage will be calculated on this entity
     * @param predict predicted copy of target
     * @return damage value in Float format
     */
    public static float getExplosionDamageWPredict(Vec3d explosionPos, PlayerEntity target, Box predict, boolean optimized) {
        if (mc.world == null || mc.player == null || mc.world.getDifficulty() == Difficulty.PEACEFUL) {
            return 0f;
        }

        if (target == null || predict == null) {
            return 0f;
        }

        MutableExplosion mutableExplosion = getMutableExplosion(explosionPos);
        DamageSource damageSource = Explosion.createDamageSource(mc.world, mc.player);

        if (!new Box(
                MathHelper.floor(explosionPos.x - 11d),
                MathHelper.floor(explosionPos.y - 11d),
                MathHelper.floor(explosionPos.z - 11d),
                MathHelper.floor(explosionPos.x + 13d),
                MathHelper.floor(explosionPos.y + 13d),
                MathHelper.floor(explosionPos.z + 13d)
        ).intersects(predict)) {
            return 0f;
        }

        if (!target.isImmuneToExplosion(mutableExplosion) && !target.isInvulnerable()) {
            double distExposure = predict.getCenter().add(0, -0.9, 0).squaredDistanceTo(explosionPos) / 144.0;
            if (distExposure <= 1.0) {
                terrainIgnore = resolveIgnoreTerrain();
                double exposure = getExposure(explosionPos, predict, optimized);
                terrainIgnore = false;
                double finalExposure = (1.0 - distExposure) * exposure;

                float toDamage = (float) Math.floor((finalExposure * finalExposure + finalExposure) / 2.0 * 7.0 * 12.0 + 1.0);

                if (mc.world.getDifficulty() == Difficulty.EASY) {
                    toDamage = Math.min(toDamage / 2f + 1f, toDamage);
                } else if (mc.world.getDifficulty() == Difficulty.HARD) {
                    toDamage = toDamage * 3f / 2f;
                }

                toDamage = DamageUtil.getDamageLeft(
                        target,
                        toDamage,
                        damageSource,
                        target.getArmor(),
                        (float) Objects.requireNonNull(target.getAttributeInstance(EntityAttributes.ARMOR_TOUGHNESS)).getValue()
                );

                if (target.hasStatusEffect(StatusEffects.RESISTANCE)) {
                    int resistance = 25 - (Objects.requireNonNull(target.getStatusEffect(StatusEffects.RESISTANCE)).getAmplifier() + 1) * 5;
                    float resistanceScaled = toDamage * resistance;
                    toDamage = Math.max(resistanceScaled / 25f, 0f);
                }

                if (toDamage <= 0f) {
                    toDamage = 0f;
                } else {
                    float protAmount = resolveAssumeBestArmor() ? 32f : getProtectionAmount(target.getArmorItems());
                    if (protAmount > 0) {
                        toDamage = DamageUtil.getInflictedDamage(toDamage, protAmount);
                    }
                }

                return toDamage;
            }
        }
        return 0f;
    }

    /**
     * Returns the BlockHitResult of the block without considering other blocks.
     *
     * @param context context with point of player's eyes and final aiming point
     * @param block position of block
     * @return BlockHitResult
     */
    public static BlockHitResult rayCastBlock(RaycastContext context, BlockPos block) {
        return BlockView.raycast(context.getStart(), context.getEnd(), context, (raycastContext, blockPos) -> {
            BlockState blockState;

            if (!blockPos.equals(block)) {
                blockState = Blocks.AIR.getDefaultState();
            } else {
                blockState = Blocks.OBSIDIAN.getDefaultState();
            }

            Vec3d vec3d = raycastContext.getStart();
            Vec3d vec3d2 = raycastContext.getEnd();
            VoxelShape voxelShape = raycastContext.getBlockShape(blockState, mc.world, blockPos);
            BlockHitResult blockHitResult = mc.world.raycastBlock(vec3d, vec3d2, blockPos, voxelShape, blockState);
            VoxelShape voxelShape2 = VoxelShapes.empty();
            BlockHitResult blockHitResult2 = voxelShape2.raycast(vec3d, vec3d2, blockPos);

            double d = blockHitResult == null ? Double.MAX_VALUE : raycastContext.getStart().squaredDistanceTo(blockHitResult.getPos());
            double e = blockHitResult2 == null ? Double.MAX_VALUE : raycastContext.getStart().squaredDistanceTo(blockHitResult2.getPos());

            return d <= e ? blockHitResult : blockHitResult2;
        }, raycastContext -> {
            Vec3d vec3d = raycastContext.getStart().subtract(raycastContext.getEnd());
            return BlockHitResult.createMissed(
                    raycastContext.getEnd(),
                    Direction.getFacing(vec3d.x, vec3d.y, vec3d.z),
                    BlockPos.ofFloored(raycastContext.getEnd())
            );
        });
    }

    private static float getExposureGhost(Vec3d source, Entity entity, BlockPos pos) {
        Box box = entity.getBoundingBox();
        double d = 1.0 / ((box.maxX - box.minX) * 2.0 + 1.0);
        double e = 1.0 / ((box.maxY - box.minY) * 2.0 + 1.0);
        double f = 1.0 / ((box.maxZ - box.minZ) * 2.0 + 1.0);
        double g = (1.0 - Math.floor(1.0 / d) * d) / 2.0;
        double h = (1.0 - Math.floor(1.0 / f) * f) / 2.0;

        if (d < 0.0 || e < 0.0 || f < 0.0) {
            return 0.0f;
        }

        int i = 0;
        int j = 0;

        for (double k = 0.0; k <= 1.0; k += d) {
            for (double l = 0.0; l <= 1.0; l += e) {
                for (double m = 0.0; m <= 1.0; m += f) {
                    double n = MathHelper.lerp(k, box.minX, box.maxX);
                    double o = MathHelper.lerp(l, box.minY, box.maxY);
                    double p = MathHelper.lerp(m, box.minZ, box.maxZ);
                    Vec3d vec3d = new Vec3d(n + g, o, p + h);
                    if (raycastGhost(new RaycastContext(vec3d, source, RaycastContext.ShapeType.COLLIDER, RaycastContext.FluidHandling.NONE, entity), pos).getType() == HitResult.Type.MISS) {
                        ++i;
                    }
                    ++j;
                }
            }
        }

        return (float) i / (float) j;
    }

    private static float getExposureRemoved(Vec3d source, Entity entity, BlockPos pos) {
        Box box = entity.getBoundingBox();
        double d = 1.0 / ((box.maxX - box.minX) * 2.0 + 1.0);
        double e = 1.0 / ((box.maxY - box.minY) * 2.0 + 1.0);
        double f = 1.0 / ((box.maxZ - box.minZ) * 2.0 + 1.0);
        double g = (1.0 - Math.floor(1.0 / d) * d) / 2.0;
        double h = (1.0 - Math.floor(1.0 / f) * f) / 2.0;

        if (d < 0.0 || e < 0.0 || f < 0.0) {
            return 0.0f;
        }

        int i = 0;
        int j = 0;

        for (double k = 0.0; k <= 1.0; k += d) {
            for (double l = 0.0; l <= 1.0; l += e) {
                for (double m = 0.0; m <= 1.0; m += f) {
                    double n = MathHelper.lerp(k, box.minX, box.maxX);
                    double o = MathHelper.lerp(l, box.minY, box.maxY);
                    double p = MathHelper.lerp(m, box.minZ, box.maxZ);
                    Vec3d vec3d = new Vec3d(n + g, o, p + h);
                    if (raycastRemoved(new RaycastContext(vec3d, source, RaycastContext.ShapeType.COLLIDER, RaycastContext.FluidHandling.NONE, entity), pos).getType() == HitResult.Type.MISS) {
                        ++i;
                    }
                    ++j;
                }
            }
        }

        return (float) i / (float) j;
    }

    public static float getExposure(Vec3d source, Box box, boolean optimized) {
        if (!optimized) {
            return getExposure(source, box);
        }

        int miss = 0;
        int hit = 0;

        for (int k = 0; k <= 1; k += 1) {
            for (int l = 0; l <= 1; l += 1) {
                for (int m = 0; m <= 1; m += 1) {
                    double n = MathHelper.lerp(k, box.minX, box.maxX);
                    double o = MathHelper.lerp(l, box.minY, box.maxY);
                    double p = MathHelper.lerp(m, box.minZ, box.maxZ);
                    Vec3d vec3d = new Vec3d(n, o, p);
                    if (raycast(vec3d, source, resolveIgnoreTerrain()) == HitResult.Type.MISS) {
                        ++miss;
                    }
                    ++hit;
                }
            }
        }
        return (float) miss / (float) hit;
    }

    public static float getExposure(Vec3d source, Box box) {
        double d = 0.4545454446934474;
        double e = 0.21739130885479366;
        double f = 0.4545454446934474;

        int i = 0;
        int j = 0;

        for (double k = 0.0; k <= 1.0; k += d) {
            for (double l = 0.0; l <= 1.0; l += e) {
                for (double m = 0.0; m <= 1.0; m += f) {
                    double n = MathHelper.lerp(k, box.minX, box.maxX);
                    double o = MathHelper.lerp(l, box.minY, box.maxY);
                    double p = MathHelper.lerp(m, box.minZ, box.maxZ);
                    Vec3d vec3d = new Vec3d(n + 0.045454555306552624, o, p + 0.045454555306552624);
                    if (raycast(vec3d, source, resolveIgnoreTerrain()) == HitResult.Type.MISS) {
                        ++i;
                    }
                    ++j;
                }
            }
        }

        return (float) i / (float) j;
    }

    private static BlockHitResult raycastGhost(RaycastContext context, BlockPos bPos) {
        return BlockView.raycast(context.getStart(), context.getEnd(), context, (innerContext, pos) -> {
            Vec3d vec3d = innerContext.getStart();
            Vec3d vec3d2 = innerContext.getEnd();

            BlockState blockState;

            if (!pos.equals(bPos)) {
                blockState = mc.world.getBlockState(bPos);
            } else {
                blockState = Blocks.OBSIDIAN.getDefaultState();
            }

            VoxelShape voxelShape = innerContext.getBlockShape(blockState, mc.world, pos);
            BlockHitResult blockHitResult = mc.world.raycastBlock(vec3d, vec3d2, pos, voxelShape, blockState);
            BlockHitResult blockHitResult2 = VoxelShapes.empty().raycast(vec3d, vec3d2, pos);
            double d = blockHitResult == null ? Double.MAX_VALUE : innerContext.getStart().squaredDistanceTo(blockHitResult.getPos());
            double e = blockHitResult2 == null ? Double.MAX_VALUE : innerContext.getStart().squaredDistanceTo(blockHitResult2.getPos());
            return d <= e ? blockHitResult : blockHitResult2;
        }, innerContext -> {
            Vec3d vec3d = innerContext.getStart().subtract(innerContext.getEnd());
            return BlockHitResult.createMissed(innerContext.getEnd(), Direction.getFacing(vec3d.x, vec3d.y, vec3d.z), BlockPos.ofFloored(innerContext.getEnd()));
        });
    }

    private static BlockHitResult raycastRemoved(RaycastContext context, BlockPos removedPos) {
        return BlockView.raycast(context.getStart(), context.getEnd(), context, (innerContext, pos) -> {
            Vec3d vec3d = innerContext.getStart();
            Vec3d vec3d2 = innerContext.getEnd();

            BlockState blockState = pos.equals(removedPos)
                    ? Blocks.AIR.getDefaultState()
                    : mc.world.getBlockState(pos);

            VoxelShape voxelShape = innerContext.getBlockShape(blockState, mc.world, pos);
            BlockHitResult blockHitResult = mc.world.raycastBlock(vec3d, vec3d2, pos, voxelShape, blockState);
            BlockHitResult blockHitResult2 = VoxelShapes.empty().raycast(vec3d, vec3d2, pos);
            double d = blockHitResult == null ? Double.MAX_VALUE : innerContext.getStart().squaredDistanceTo(blockHitResult.getPos());
            double e = blockHitResult2 == null ? Double.MAX_VALUE : innerContext.getStart().squaredDistanceTo(blockHitResult2.getPos());
            return d <= e ? blockHitResult : blockHitResult2;
        }, innerContext -> {
            Vec3d vec3d = innerContext.getStart().subtract(innerContext.getEnd());
            return BlockHitResult.createMissed(innerContext.getEnd(), Direction.getFacing(vec3d.x, vec3d.y, vec3d.z), BlockPos.ofFloored(innerContext.getEnd()));
        });
    }

    public static HitResult.Type raycast(Vec3d start, Vec3d end, boolean ignoreTerrain) {
        return BlockView.raycast(start, end, null, (innerContext, blockPos) -> {
            BlockState blockState = mc.world.getBlockState(blockPos);
            if (blockState.getBlock().getBlastResistance() < 600 && ignoreTerrain) {
                return null;
            }
            BlockHitResult hitResult = blockState.getCollisionShape(mc.world, blockPos).raycast(start, end, blockPos);
            return hitResult == null ? null : hitResult.getType();
        }, innerContext -> HitResult.Type.MISS);
    }

    public static int getProtectionAmount(Iterable<ItemStack> equipment) {
        MutableInt mutableInt = new MutableInt();
        equipment.forEach(i -> mutableInt.add(getProtectionAmount(i)));
        return mutableInt.intValue();
    }

    public static int getProtectionAmount(ItemStack stack) {
        int modifierBlast = 0;
        int modifier = 0;

        ItemEnchantmentsComponent enchantments = EnchantmentHelper.getEnchantments(stack);
        for (var entry : enchantments.getEnchantmentEntries()) {
            RegistryEntry<Enchantment> enchantment = entry.getKey();
            String id = enchantment.getIdAsString();
            if ("minecraft:blast_protection".equals(id)) {
                modifierBlast = entry.getIntValue();
            } else if ("minecraft:protection".equals(id)) {
                modifier = entry.getIntValue();
            }
        }

        return modifierBlast * 2 + modifier;
    }

    private static MutableExplosion getMutableExplosion(Vec3d explosionPos) {
        MutableExplosion mutable;
        if (explosion instanceof MutableExplosion existing) {
            mutable = existing;
        } else {
            mutable = new MutableExplosion();
            explosion = mutable;
        }

        mutable.setPosition(explosionPos);
        mutable.setEntity(mc.player);
        mutable.setPower(6.0f);
        mutable.setWorld(mc.world);
        return mutable;
    }

    private static boolean resolveIgnoreTerrain() {
        try {
            return sweetie.evaware.client.features.modules.combat.crystalaura.CrystalAuraModule
                    .getInstance()
                    .processor
                    .ignoreTerrain
                    .getValue();
        } catch (Throwable ignored) {
            return terrainIgnore;
        }
    }

    private static boolean resolveAssumeBestArmor() {
        return assumeBestArmor;
    }

    private static final class MutableExplosion implements Explosion {
        private ServerWorld world;
        private Entity entity;
        private float power = 6.0f;
        private Vec3d position = Vec3d.ZERO;

        void setWorld(@Nullable World world) {
            this.world = world instanceof ServerWorld serverWorld ? serverWorld : null;
        }

        void setEntity(Entity entity) {
            this.entity = entity;
        }

        void setPower(float power) {
            this.power = power;
        }

        void setPosition(Vec3d position) {
            this.position = position;
        }

        @Override
        public ServerWorld getWorld() {
            return world;
        }

        @Override
        public DestructionType getDestructionType() {
            return DestructionType.DESTROY;
        }

        @Override
        public LivingEntity getCausingEntity() {
            return entity instanceof LivingEntity living ? living : null;
        }

        @Override
        public Entity getEntity() {
            return entity;
        }

        @Override
        public float getPower() {
            return power;
        }

        @Override
        public Vec3d getPosition() {
            return position;
        }

        @Override
        public boolean canTriggerBlocks() {
            return false;
        }

        @Override
        public boolean preservesDecorativeEntities() {
            return false;
        }
    }
}
predictutil:
Expand Collapse Copy
package sweetie.evaware.api.utils.math;

import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;
import sweetie.evaware.api.system.interfaces.QuickImports;

public class PredictUtility implements QuickImports {
    public static Vec3d predictPosition(PlayerEntity entity, int ticks) {
        if (entity == null || mc.world == null) {
            return null;
        }

        Vec3d posVec = new Vec3d(entity.getX(), entity.getY(), entity.getZ());

        double motionX = entity.getVelocity().getX();
        double motionZ = entity.getVelocity().getZ();

        for (int i = 0; i < ticks; i++) {
            float hbDeltaX = motionX > 0 ? 0.3f : -0.3f;
            float hbDeltaZ = motionZ > 0 ? 0.3f : -0.3f;

            if (!mc.world.isAir(BlockPos.ofFloored(posVec.add(motionX + hbDeltaX, 0.1, motionZ + hbDeltaZ)))
                    || !mc.world.isAir(BlockPos.ofFloored(posVec.add(motionX + hbDeltaX, 1, motionZ + hbDeltaZ)))) {
                motionX = 0;
                motionZ = 0;
            }
            posVec = posVec.add(motionX, 0, motionZ);
        }

        return posVec;
    }

    public static Box predictBox(PlayerEntity entity, int ticks) {
        Vec3d posVec = predictPosition(entity, ticks);
        if (posVec == null) {
            return null;
        }
        return entity.getBoundingBox().offset(entity.getPos().relativize(posVec));
    }
}
 
ExplosionUtility:
Expand Collapse Copy
package sweetie.evaware.api.utils.world;

import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.component.type.ItemEnchantmentsComponent;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.DamageUtil;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.Difficulty;
import net.minecraft.world.RaycastContext;
import net.minecraft.world.World;
import net.minecraft.world.explosion.Explosion;
import org.apache.commons.lang3.mutable.MutableInt;
import org.jetbrains.annotations.Nullable;
import sweetie.evaware.api.system.interfaces.QuickImports;
import sweetie.evaware.api.utils.math.PredictUtility;

import java.util.Objects;

public final class ExplosionUtility implements QuickImports {

    public static boolean terrainIgnore = false;
    public static boolean assumeBestArmor = false;
    public static Explosion explosion;

    private ExplosionUtility() {
    }

    /**
     * Calculate target damage based on crystal position and target. Uses AutoCrystal settings so use only in AutoCrystal.
     *
     * @param crystalPos the position of the crystal whose damage is to be calculated
     * @param target the damage will be calculated on this entity
     * @param optimized use light calculate
     * @return damage value in Float format
     */
    public static float getAutoCrystalDamage(Vec3d crystalPos, PlayerEntity target, int predictTicks, boolean optimized) {
        if (predictTicks == 0) {
            return getExplosionDamage(crystalPos, target, optimized);
        }
        return getExplosionDamageWPredict(crystalPos, target, PredictUtility.predictBox(target, predictTicks), optimized);
    }

    /**
     * Calculate self damage based on crystal position and self extrapolation (predict).
     *
     * @param explosionPos the position of the explosion whose damage is to be calculated
     * @param predictTicks the number of game ticks for which the player's position should be predicted
     * @param optimized use light calculate
     * @return damage value in Float format
     */
    public static float getSelfExplosionDamage(Vec3d explosionPos, int predictTicks, boolean optimized) {
        return getAutoCrystalDamage(explosionPos, mc.player, predictTicks, optimized);
    }

    /**
     * Calculate target damage based on crystal position and target.
     *
     * @param explosionPos the position of the explosion whose damage is to be calculated
     * @param target the damage will be calculated on this entity
     * @param optimized use light calculate
     * @return damage value in Float format
     */
    public static float getExplosionDamage(Vec3d explosionPos, PlayerEntity target, boolean optimized) {
        if (mc.world == null || mc.player == null || mc.world.getDifficulty() == Difficulty.PEACEFUL || target == null) {
            return 0f;
        }

        MutableExplosion mutableExplosion = getMutableExplosion(explosionPos);
        DamageSource damageSource = Explosion.createDamageSource(mc.world, mc.player);

        if (!new Box(
                MathHelper.floor(explosionPos.x - 11),
                MathHelper.floor(explosionPos.y - 11),
                MathHelper.floor(explosionPos.z - 11),
                MathHelper.floor(explosionPos.x + 13),
                MathHelper.floor(explosionPos.y + 13),
                MathHelper.floor(explosionPos.z + 13)
        ).intersects(target.getBoundingBox())) {
            return 0f;
        }

        if (!target.isImmuneToExplosion(mutableExplosion) && !target.isInvulnerable()) {
            double distExposure = target.squaredDistanceTo(explosionPos) / 144.0;
            if (distExposure <= 1.0) {
                terrainIgnore = resolveIgnoreTerrain();
                double exposure = getExposure(explosionPos, target.getBoundingBox(), optimized);
                terrainIgnore = false;
                double finalExposure = (1.0 - distExposure) * exposure;

                float toDamage = (float) Math.floor((finalExposure * finalExposure + finalExposure) / 2.0 * 7.0 * 12.0 + 1.0);

                if (mc.world.getDifficulty() == Difficulty.EASY) {
                    toDamage = Math.min(toDamage / 2f + 1f, toDamage);
                } else if (mc.world.getDifficulty() == Difficulty.HARD) {
                    toDamage = toDamage * 3f / 2f;
                }

                toDamage = DamageUtil.getDamageLeft(
                        target,
                        toDamage,
                        damageSource,
                        target.getArmor(),
                        (float) Objects.requireNonNull(target.getAttributeInstance(EntityAttributes.ARMOR_TOUGHNESS)).getValue()
                );

                if (target.hasStatusEffect(StatusEffects.RESISTANCE)) {
                    int resistance = 25 - (Objects.requireNonNull(target.getStatusEffect(StatusEffects.RESISTANCE)).getAmplifier() + 1) * 5;
                    float resistanceScaled = toDamage * resistance;
                    toDamage = Math.max(resistanceScaled / 25f, 0f);
                }

                if (toDamage <= 0f) {
                    toDamage = 0f;
                } else {
                    float protAmount = resolveAssumeBestArmor() ? 32f : getProtectionAmount(target.getArmorItems());
                    if (protAmount > 0) {
                        toDamage = DamageUtil.getInflictedDamage(toDamage, protAmount);
                    }
                }

                return toDamage;
            }
        }
        return 0f;
    }

    /**
     * Calculate target damage based on crystal position, target and predicted copy of target.
     *
     * @param explosionPos the position of the explosion whose damage is to be calculated
     * @param target the damage will be calculated on this entity
     * @param predict predicted copy of target
     * @return damage value in Float format
     */
    public static float getExplosionDamageWPredict(Vec3d explosionPos, PlayerEntity target, Box predict, boolean optimized) {
        if (mc.world == null || mc.player == null || mc.world.getDifficulty() == Difficulty.PEACEFUL) {
            return 0f;
        }

        if (target == null || predict == null) {
            return 0f;
        }

        MutableExplosion mutableExplosion = getMutableExplosion(explosionPos);
        DamageSource damageSource = Explosion.createDamageSource(mc.world, mc.player);

        if (!new Box(
                MathHelper.floor(explosionPos.x - 11d),
                MathHelper.floor(explosionPos.y - 11d),
                MathHelper.floor(explosionPos.z - 11d),
                MathHelper.floor(explosionPos.x + 13d),
                MathHelper.floor(explosionPos.y + 13d),
                MathHelper.floor(explosionPos.z + 13d)
        ).intersects(predict)) {
            return 0f;
        }

        if (!target.isImmuneToExplosion(mutableExplosion) && !target.isInvulnerable()) {
            double distExposure = predict.getCenter().add(0, -0.9, 0).squaredDistanceTo(explosionPos) / 144.0;
            if (distExposure <= 1.0) {
                terrainIgnore = resolveIgnoreTerrain();
                double exposure = getExposure(explosionPos, predict, optimized);
                terrainIgnore = false;
                double finalExposure = (1.0 - distExposure) * exposure;

                float toDamage = (float) Math.floor((finalExposure * finalExposure + finalExposure) / 2.0 * 7.0 * 12.0 + 1.0);

                if (mc.world.getDifficulty() == Difficulty.EASY) {
                    toDamage = Math.min(toDamage / 2f + 1f, toDamage);
                } else if (mc.world.getDifficulty() == Difficulty.HARD) {
                    toDamage = toDamage * 3f / 2f;
                }

                toDamage = DamageUtil.getDamageLeft(
                        target,
                        toDamage,
                        damageSource,
                        target.getArmor(),
                        (float) Objects.requireNonNull(target.getAttributeInstance(EntityAttributes.ARMOR_TOUGHNESS)).getValue()
                );

                if (target.hasStatusEffect(StatusEffects.RESISTANCE)) {
                    int resistance = 25 - (Objects.requireNonNull(target.getStatusEffect(StatusEffects.RESISTANCE)).getAmplifier() + 1) * 5;
                    float resistanceScaled = toDamage * resistance;
                    toDamage = Math.max(resistanceScaled / 25f, 0f);
                }

                if (toDamage <= 0f) {
                    toDamage = 0f;
                } else {
                    float protAmount = resolveAssumeBestArmor() ? 32f : getProtectionAmount(target.getArmorItems());
                    if (protAmount > 0) {
                        toDamage = DamageUtil.getInflictedDamage(toDamage, protAmount);
                    }
                }

                return toDamage;
            }
        }
        return 0f;
    }

    /**
     * Returns the BlockHitResult of the block without considering other blocks.
     *
     * @param context context with point of player's eyes and final aiming point
     * @param block position of block
     * @return BlockHitResult
     */
    public static BlockHitResult rayCastBlock(RaycastContext context, BlockPos block) {
        return BlockView.raycast(context.getStart(), context.getEnd(), context, (raycastContext, blockPos) -> {
            BlockState blockState;

            if (!blockPos.equals(block)) {
                blockState = Blocks.AIR.getDefaultState();
            } else {
                blockState = Blocks.OBSIDIAN.getDefaultState();
            }

            Vec3d vec3d = raycastContext.getStart();
            Vec3d vec3d2 = raycastContext.getEnd();
            VoxelShape voxelShape = raycastContext.getBlockShape(blockState, mc.world, blockPos);
            BlockHitResult blockHitResult = mc.world.raycastBlock(vec3d, vec3d2, blockPos, voxelShape, blockState);
            VoxelShape voxelShape2 = VoxelShapes.empty();
            BlockHitResult blockHitResult2 = voxelShape2.raycast(vec3d, vec3d2, blockPos);

            double d = blockHitResult == null ? Double.MAX_VALUE : raycastContext.getStart().squaredDistanceTo(blockHitResult.getPos());
            double e = blockHitResult2 == null ? Double.MAX_VALUE : raycastContext.getStart().squaredDistanceTo(blockHitResult2.getPos());

            return d <= e ? blockHitResult : blockHitResult2;
        }, raycastContext -> {
            Vec3d vec3d = raycastContext.getStart().subtract(raycastContext.getEnd());
            return BlockHitResult.createMissed(
                    raycastContext.getEnd(),
                    Direction.getFacing(vec3d.x, vec3d.y, vec3d.z),
                    BlockPos.ofFloored(raycastContext.getEnd())
            );
        });
    }

    private static float getExposureGhost(Vec3d source, Entity entity, BlockPos pos) {
        Box box = entity.getBoundingBox();
        double d = 1.0 / ((box.maxX - box.minX) * 2.0 + 1.0);
        double e = 1.0 / ((box.maxY - box.minY) * 2.0 + 1.0);
        double f = 1.0 / ((box.maxZ - box.minZ) * 2.0 + 1.0);
        double g = (1.0 - Math.floor(1.0 / d) * d) / 2.0;
        double h = (1.0 - Math.floor(1.0 / f) * f) / 2.0;

        if (d < 0.0 || e < 0.0 || f < 0.0) {
            return 0.0f;
        }

        int i = 0;
        int j = 0;

        for (double k = 0.0; k <= 1.0; k += d) {
            for (double l = 0.0; l <= 1.0; l += e) {
                for (double m = 0.0; m <= 1.0; m += f) {
                    double n = MathHelper.lerp(k, box.minX, box.maxX);
                    double o = MathHelper.lerp(l, box.minY, box.maxY);
                    double p = MathHelper.lerp(m, box.minZ, box.maxZ);
                    Vec3d vec3d = new Vec3d(n + g, o, p + h);
                    if (raycastGhost(new RaycastContext(vec3d, source, RaycastContext.ShapeType.COLLIDER, RaycastContext.FluidHandling.NONE, entity), pos).getType() == HitResult.Type.MISS) {
                        ++i;
                    }
                    ++j;
                }
            }
        }

        return (float) i / (float) j;
    }

    private static float getExposureRemoved(Vec3d source, Entity entity, BlockPos pos) {
        Box box = entity.getBoundingBox();
        double d = 1.0 / ((box.maxX - box.minX) * 2.0 + 1.0);
        double e = 1.0 / ((box.maxY - box.minY) * 2.0 + 1.0);
        double f = 1.0 / ((box.maxZ - box.minZ) * 2.0 + 1.0);
        double g = (1.0 - Math.floor(1.0 / d) * d) / 2.0;
        double h = (1.0 - Math.floor(1.0 / f) * f) / 2.0;

        if (d < 0.0 || e < 0.0 || f < 0.0) {
            return 0.0f;
        }

        int i = 0;
        int j = 0;

        for (double k = 0.0; k <= 1.0; k += d) {
            for (double l = 0.0; l <= 1.0; l += e) {
                for (double m = 0.0; m <= 1.0; m += f) {
                    double n = MathHelper.lerp(k, box.minX, box.maxX);
                    double o = MathHelper.lerp(l, box.minY, box.maxY);
                    double p = MathHelper.lerp(m, box.minZ, box.maxZ);
                    Vec3d vec3d = new Vec3d(n + g, o, p + h);
                    if (raycastRemoved(new RaycastContext(vec3d, source, RaycastContext.ShapeType.COLLIDER, RaycastContext.FluidHandling.NONE, entity), pos).getType() == HitResult.Type.MISS) {
                        ++i;
                    }
                    ++j;
                }
            }
        }

        return (float) i / (float) j;
    }

    public static float getExposure(Vec3d source, Box box, boolean optimized) {
        if (!optimized) {
            return getExposure(source, box);
        }

        int miss = 0;
        int hit = 0;

        for (int k = 0; k <= 1; k += 1) {
            for (int l = 0; l <= 1; l += 1) {
                for (int m = 0; m <= 1; m += 1) {
                    double n = MathHelper.lerp(k, box.minX, box.maxX);
                    double o = MathHelper.lerp(l, box.minY, box.maxY);
                    double p = MathHelper.lerp(m, box.minZ, box.maxZ);
                    Vec3d vec3d = new Vec3d(n, o, p);
                    if (raycast(vec3d, source, resolveIgnoreTerrain()) == HitResult.Type.MISS) {
                        ++miss;
                    }
                    ++hit;
                }
            }
        }
        return (float) miss / (float) hit;
    }

    public static float getExposure(Vec3d source, Box box) {
        double d = 0.4545454446934474;
        double e = 0.21739130885479366;
        double f = 0.4545454446934474;

        int i = 0;
        int j = 0;

        for (double k = 0.0; k <= 1.0; k += d) {
            for (double l = 0.0; l <= 1.0; l += e) {
                for (double m = 0.0; m <= 1.0; m += f) {
                    double n = MathHelper.lerp(k, box.minX, box.maxX);
                    double o = MathHelper.lerp(l, box.minY, box.maxY);
                    double p = MathHelper.lerp(m, box.minZ, box.maxZ);
                    Vec3d vec3d = new Vec3d(n + 0.045454555306552624, o, p + 0.045454555306552624);
                    if (raycast(vec3d, source, resolveIgnoreTerrain()) == HitResult.Type.MISS) {
                        ++i;
                    }
                    ++j;
                }
            }
        }

        return (float) i / (float) j;
    }

    private static BlockHitResult raycastGhost(RaycastContext context, BlockPos bPos) {
        return BlockView.raycast(context.getStart(), context.getEnd(), context, (innerContext, pos) -> {
            Vec3d vec3d = innerContext.getStart();
            Vec3d vec3d2 = innerContext.getEnd();

            BlockState blockState;

            if (!pos.equals(bPos)) {
                blockState = mc.world.getBlockState(bPos);
            } else {
                blockState = Blocks.OBSIDIAN.getDefaultState();
            }

            VoxelShape voxelShape = innerContext.getBlockShape(blockState, mc.world, pos);
            BlockHitResult blockHitResult = mc.world.raycastBlock(vec3d, vec3d2, pos, voxelShape, blockState);
            BlockHitResult blockHitResult2 = VoxelShapes.empty().raycast(vec3d, vec3d2, pos);
            double d = blockHitResult == null ? Double.MAX_VALUE : innerContext.getStart().squaredDistanceTo(blockHitResult.getPos());
            double e = blockHitResult2 == null ? Double.MAX_VALUE : innerContext.getStart().squaredDistanceTo(blockHitResult2.getPos());
            return d <= e ? blockHitResult : blockHitResult2;
        }, innerContext -> {
            Vec3d vec3d = innerContext.getStart().subtract(innerContext.getEnd());
            return BlockHitResult.createMissed(innerContext.getEnd(), Direction.getFacing(vec3d.x, vec3d.y, vec3d.z), BlockPos.ofFloored(innerContext.getEnd()));
        });
    }

    private static BlockHitResult raycastRemoved(RaycastContext context, BlockPos removedPos) {
        return BlockView.raycast(context.getStart(), context.getEnd(), context, (innerContext, pos) -> {
            Vec3d vec3d = innerContext.getStart();
            Vec3d vec3d2 = innerContext.getEnd();

            BlockState blockState = pos.equals(removedPos)
                    ? Blocks.AIR.getDefaultState()
                    : mc.world.getBlockState(pos);

            VoxelShape voxelShape = innerContext.getBlockShape(blockState, mc.world, pos);
            BlockHitResult blockHitResult = mc.world.raycastBlock(vec3d, vec3d2, pos, voxelShape, blockState);
            BlockHitResult blockHitResult2 = VoxelShapes.empty().raycast(vec3d, vec3d2, pos);
            double d = blockHitResult == null ? Double.MAX_VALUE : innerContext.getStart().squaredDistanceTo(blockHitResult.getPos());
            double e = blockHitResult2 == null ? Double.MAX_VALUE : innerContext.getStart().squaredDistanceTo(blockHitResult2.getPos());
            return d <= e ? blockHitResult : blockHitResult2;
        }, innerContext -> {
            Vec3d vec3d = innerContext.getStart().subtract(innerContext.getEnd());
            return BlockHitResult.createMissed(innerContext.getEnd(), Direction.getFacing(vec3d.x, vec3d.y, vec3d.z), BlockPos.ofFloored(innerContext.getEnd()));
        });
    }

    public static HitResult.Type raycast(Vec3d start, Vec3d end, boolean ignoreTerrain) {
        return BlockView.raycast(start, end, null, (innerContext, blockPos) -> {
            BlockState blockState = mc.world.getBlockState(blockPos);
            if (blockState.getBlock().getBlastResistance() < 600 && ignoreTerrain) {
                return null;
            }
            BlockHitResult hitResult = blockState.getCollisionShape(mc.world, blockPos).raycast(start, end, blockPos);
            return hitResult == null ? null : hitResult.getType();
        }, innerContext -> HitResult.Type.MISS);
    }

    public static int getProtectionAmount(Iterable<ItemStack> equipment) {
        MutableInt mutableInt = new MutableInt();
        equipment.forEach(i -> mutableInt.add(getProtectionAmount(i)));
        return mutableInt.intValue();
    }

    public static int getProtectionAmount(ItemStack stack) {
        int modifierBlast = 0;
        int modifier = 0;

        ItemEnchantmentsComponent enchantments = EnchantmentHelper.getEnchantments(stack);
        for (var entry : enchantments.getEnchantmentEntries()) {
            RegistryEntry<Enchantment> enchantment = entry.getKey();
            String id = enchantment.getIdAsString();
            if ("minecraft:blast_protection".equals(id)) {
                modifierBlast = entry.getIntValue();
            } else if ("minecraft:protection".equals(id)) {
                modifier = entry.getIntValue();
            }
        }

        return modifierBlast * 2 + modifier;
    }

    private static MutableExplosion getMutableExplosion(Vec3d explosionPos) {
        MutableExplosion mutable;
        if (explosion instanceof MutableExplosion existing) {
            mutable = existing;
        } else {
            mutable = new MutableExplosion();
            explosion = mutable;
        }

        mutable.setPosition(explosionPos);
        mutable.setEntity(mc.player);
        mutable.setPower(6.0f);
        mutable.setWorld(mc.world);
        return mutable;
    }

    private static boolean resolveIgnoreTerrain() {
        try {
            return sweetie.evaware.client.features.modules.combat.crystalaura.CrystalAuraModule
                    .getInstance()
                    .processor
                    .ignoreTerrain
                    .getValue();
        } catch (Throwable ignored) {
            return terrainIgnore;
        }
    }

    private static boolean resolveAssumeBestArmor() {
        return assumeBestArmor;
    }

    private static final class MutableExplosion implements Explosion {
        private ServerWorld world;
        private Entity entity;
        private float power = 6.0f;
        private Vec3d position = Vec3d.ZERO;

        void setWorld(@Nullable World world) {
            this.world = world instanceof ServerWorld serverWorld ? serverWorld : null;
        }

        void setEntity(Entity entity) {
            this.entity = entity;
        }

        void setPower(float power) {
            this.power = power;
        }

        void setPosition(Vec3d position) {
            this.position = position;
        }

        @Override
        public ServerWorld getWorld() {
            return world;
        }

        @Override
        public DestructionType getDestructionType() {
            return DestructionType.DESTROY;
        }

        @Override
        public LivingEntity getCausingEntity() {
            return entity instanceof LivingEntity living ? living : null;
        }

        @Override
        public Entity getEntity() {
            return entity;
        }

        @Override
        public float getPower() {
            return power;
        }

        @Override
        public Vec3d getPosition() {
            return position;
        }

        @Override
        public boolean canTriggerBlocks() {
            return false;
        }

        @Override
        public boolean preservesDecorativeEntities() {
            return false;
        }
    }
}
predictutil:
Expand Collapse Copy
package sweetie.evaware.api.utils.math;

import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;
import sweetie.evaware.api.system.interfaces.QuickImports;

public class PredictUtility implements QuickImports {
    public static Vec3d predictPosition(PlayerEntity entity, int ticks) {
        if (entity == null || mc.world == null) {
            return null;
        }

        Vec3d posVec = new Vec3d(entity.getX(), entity.getY(), entity.getZ());

        double motionX = entity.getVelocity().getX();
        double motionZ = entity.getVelocity().getZ();

        for (int i = 0; i < ticks; i++) {
            float hbDeltaX = motionX > 0 ? 0.3f : -0.3f;
            float hbDeltaZ = motionZ > 0 ? 0.3f : -0.3f;

            if (!mc.world.isAir(BlockPos.ofFloored(posVec.add(motionX + hbDeltaX, 0.1, motionZ + hbDeltaZ)))
                    || !mc.world.isAir(BlockPos.ofFloored(posVec.add(motionX + hbDeltaX, 1, motionZ + hbDeltaZ)))) {
                motionX = 0;
                motionZ = 0;
            }
            posVec = posVec.add(motionX, 0, motionZ);
        }

        return posVec;
    }

    public static Box predictBox(PlayerEntity entity, int ticks) {
        Vec3d posVec = predictPosition(entity, ticks);
        if (posVec == null) {
            return null;
        }
        return entity.getBoundingBox().offset(entity.getPos().relativize(posVec));
    }
}
красавчик
 
какие утилки
у меня щас кристалл аура в 5к строк, я не особо понимаю какие именно
у тебя уже готовая кристалл аура типо под пресет под lonygrief тот же самый, или надо отдельно настраивать?
 
у тебя уже готовая кристалл аура типо под пресет под lonygrief тот же самый, или надо отдельно настраивать?
под cpvp,lonygrief + grim, короче мультисерверная, только на Sloth скоро буду делать, ибо слотх видит мою ротацию и ебет меня, так что либо анротка, либо нон ротку попробую сделать пакетную как в ауре, ибо на лунике это не пофикшено.
Да и щас у меня кристаллка чуть чуть тупит за стенками, а так она ебет очень жоска типочков
под cpvp,lonygrief + grim, короче мультисерверная, только на Sloth скоро буду делать, ибо слотх видит мою ротацию и ебет меня, так что либо анротка, либо нон ротку попробую сделать пакетную как в ауре, ибо на лунике это не пофикшено.
Да и щас у меня кристаллка чуть чуть тупит за стенками, а так она ебет очень жоска типочков
+ 5к строк
 
у тебя уже готовая кристалл аура типо под пресет под lonygrief тот же самый, или надо отдельно настраивать?
а если ты имеешь про настройки на lonygrief то данная кристаллка которая сейчас будет работать криво. А так лучше тебе настроить селф и макс демейдж и ротки и усе
 
Назад
Сверху Снизу