import * as mc from '@minecraft/server';
import stand_defaultAttack from '../default/stand_defaultAttack.js';
import titleUI from "../default/standUI.js";
import titleUIList from './_ui_/titleUIList.js';
import Vec3 from '../../../modules/Vec3.js';
import range from '../../../modules/arrayRange.js';
import Mathf from '../../../modules/Mathf.js';

export default class kingCrimson extends stand_defaultAttack {
    constructor(player) {
        super(player);
        this.standMaster = player;
        this.UI = titleUIList.ui;
        this.GUI = titleUIList.gui;
        
        this.ap_cd = this.GlobalVar(this.standMaster,"stand_skill2");
        this.ap_cd2 = this.GlobalVar(this.standMaster,"stand_skill2_2");
        this.epitaph_tick = this.GlobalVar(this.standMaster,"stand_skill3");
        this.epitaph_tick2 = this.GlobalVar(this.standMaster,"stand_skill3_2");
        this.erase_tick = this.GlobalVar(this.standMaster,"stand_skill4");
        this.erase_tick2 = this.GlobalVar(this.standMaster,"stand_skill4_2");
        this.playerHealth = this.GlobalVar(this.standMaster,"playerHealth");
        this.playerHealth2 = this.GlobalVar(this.standMaster,"playerHealth2");
        this.playerGameMode = this.GlobalVar(this.standMaster,"playerGameMode");
        this.epitaph_position = this.GlobalVar(this.standMaster,"epitaph_position");
        this.epitaph_vector = this.GlobalVar(this.standMaster,"epitaph_vector");
        this.epitaph_distance = this.GlobalVar(this.standMaster,"epitaph_distance");
        this.delay_tick = this.GlobalVar(this.standMaster,"delay_tick");
        
        this.ticking();
        // this.ticking2();
        // this.getPressurePlateMaterial = new Array("acacia", "birch", "crimson", "dark_oak", "heavy_weighted", "jungle", "light_weighted", "polished_black_stone", "spruce", "stone", "warped", "wooden");
    }
    
    ticking() {
        
        let player = this.standMaster;
        let handItem = this.getHandItem(player);
        
        let erase_cooldown = 8;
        
        this.skills_count = 2;
        
        this.LoadingGUI({
            name: "kingCrimson",
            value: this.UIslotData
        });
        
        if (!player?.hasTag("entity.in_timeStop")) {
            this.summon({
                anim_id: "king_crimson",
                sounds: [
                    "kingCrimson.summon",
                    "kingCrimson.name"
                ]
            });
            
            this.defaultAttack({
                damage: 5,
                attack_interval: 3,
                delay: 5,
                power: 0.25,
                max_fist_count: 2,
                mental: 1,
                loss: 18,
                sound1: "kingCrimson.punch"
            });
            this.quickFist({
                range: 4,
                damage: 5,
                duration: 2,
                cooldown_reply: 3,
                /*
                once_sounds: [
                    "kingCrimson.dungWorm->999"
                ],
                */
                fist_sounds: [
                    "kingCrimson.quick_fist->4"
                ],
                hit_sounds: [
                    "kingCrimson.punch->20"
                ],
                mental: {
                    value: 1,
                    interval: Math.floor(Mathf.random(20,30))
                }
            });
            this.APattack({
                range: 4,
                damage: 20,
                cooldown: 3,
                mental: 1,
                sounds: [
                    "kingCrimson.attack",
                    "kingCrimson.saying"
                ]
            });
            
            this.epitaph({
                duration: 4,
                cooldown_reply: 0.5,
                mental: {
                    value: Math.floor(Mathf.random(1,3)),
                    interval: 40
                }
            });
            
            if (!player?.hasTag("entity.in_timeErase")) {
                this.timeErase({
                    duration: 10,
                    cooldown_reply: 1,
                    mental: {
                        value: Math.floor(Mathf.random(1,3)),
                        interval: 40
                    }
                });
            }
        }
        
    }
    
    static description(player,system) {
        let _this = system;
        let menu = _this.ui();
        menu.layout(player, `
            <ui id="_stand_description_"/>
                <title text="ui.stand_settings.skills_description"/>
                    <body text="ui.how_to_use.no_stand"/>
                        <button id="skill1" text="ui.stand_settings.3.how_to_use.stand_fist" icon="textures/gui/kingCrimson/icon1"/>
                        <button id="skill2" text="ui.stand_settings.3.how_to_use.stand_ap" icon="textures/gui/kingCrimson/icon2"/>
                        <button id="skill3" text="ui.stand_settings.3.how_to_use.kingCrimson_epitaph" icon="textures/gui/kingCrimson/icon3"/>
                        <button id="skill4" text="ui.stand_settings.3.how_to_use.kingCrimson_timeErase" icon="textures/gui/kingCrimson/icon4"/>
                        <button id="close" text="ui.stand_settings.3"/>
                    </body>
                </title>
            </ui>
        `
        );
        menu.trigger("_stand_description_", e => {
            let canceled = e.canceled;
            _this.ui_using(player,0);
            
            let selection = e.getElementById;
            _this.menu_op(player);
        });
    }
    
    static eventData(_this) {
        let c = (entity) => {
            return entity !== undefined && entity?.typeId == "minecraft:player" && entity?.hasTag("standMaster.kingCrimson")
        }
        let itemUseInEraseTime = (eventData) => {
            const { source, item } = eventData;
            if (c(source)) {
                let player = source;
                player?.removeTag(`kingCrimson.timeErase`)
            }
        }
        
        _this.listenForEvent("minecraft:itemUse", (eventData) => itemUseInEraseTime(eventData));
        _this.listenForEvent("minecraft:itemUseOn", (eventData) => itemUseInEraseTime(eventData));
        _this.listenForEvent("minecraft:entityHitBlock", (eventData) => {
            let { damagingEntity, hitBlock } = eventData;
            if (c(damagingEntity)) {
                let player = damagingEntity;
                player?.removeTag(`kingCrimson.timeErase`)
            }
        })
        _this.listenForEvent("minecraft:entityHitEntity", (eventData) => {
            let { damagingEntity, hitEntity } = eventData;
            if (c(damagingEntity)) {
                let player = damagingEntity;
                player?.removeTag(`kingCrimson.timeErase`)
            }
            if (c(hitEntity)) {
                let player = hitEntity;
                if (player?.hasTag("kingCrimson.epitaph")) {
                    damagingEntity?.addTag("attackedTarget:" + player?.name);
                    player?.addTag(`kingCrimson.avoid`)
                }
            }
        })
        _this.listenForEvent("minecraft:itemStartUse", (eventData) => {
            let { itemStack, source } = eventData;
            let setTag = [
                "removeTag",
                "addTag"
            ]
            if (c(source)) {
                let item = itemStack;
                let player = source;
                if (item.typeId === "stand:skill2") {
                    if (!player?.isSneaking) {
                        let tag = "kingCrimson.timeErase";
                        player[setTag[+!player?.hasTag(tag)]](tag);
                    } else if (!player?.hasTag("kc.ban_epitaph")) {
                        let tag = "kingCrimson.epitaph";
                        player[setTag[+!player?.hasTag(tag)]](tag);
                    }
                }
            }
        });
        _this.tick(() => {
            _this.getEntities({tags:["entity.in_timeErase"],excludeTags:["kingCrimson.timeErase","isFirstCreated"],/*excludeFamilies:["inanimate"],*/excludeTypes:["minecraft:item","minecraft:xp_orb"]}).forEach(entity => {
                if (!entity?.hasTag("remove.timeErase")) {
                    if (!entity?.hasTag("entity.start_skipTime")) {
                        let timeEraseDistance = {var:1}
                        try {
                            timeEraseDistance = _this.scores(entity,"timeEraseDistance");
                        } catch(e) {
                            timeEraseDistance = {var:1}
                        }
                        let eraseVelocity = Object.fromEntries("xyz".split("").map(xyz => {
                            return [ xyz, {var:0} ]
                        }))
                        "xyz".split("").map(xyz => {
                            try {
                                eraseVelocity[xyz] = _this.scores(entity,"eraseVelocity" + xyz.toUpperCase());
                            } catch(e) {
                                eraseVelocity[xyz] = {
                                    var: 0
                                }
                            }
                            eraseVelocity[xyz].var = entity?.getVelocity()[xyz].toFixed(2) * 100
                        })
                        let eraseRotation = Object.fromEntries("xy".split("").map(xy => {
                            return [ xy, {var:0} ]
                        }))
                        "xy".split("").map(xy => {
                            try {
                                eraseRotation[xy] = _this.scores(entity,"eraseRotation" + xy.toUpperCase());
                            } catch(e) {
                                eraseRotation[xy] = {
                                    var: 0
                                }
                            }
                            eraseRotation[xy].var = entity?.getRotation()[xy].toFixed(2) * 100
                        })
                        timeEraseDistance.var = 300;
                        // console.error(timeEraseDistance.var)
                        entity?.addTag("entity.start_skipTime");
                    } else {
                        let timeEraseDistance = {var:1}
                        try {
                            timeEraseDistance = _this.scores(entity,"timeEraseDistance");
                        } catch(e) {
                            timeEraseDistance = {var:1}
                        }
                        let eraseVelocity = Object.fromEntries("xyz".split("").map(xyz => {
                            return [ xyz, {var:0} ]
                        }))
                        let velocity = Object.fromEntries("xyz".split("").map(xyz => {
                            try {
                                eraseVelocity[xyz] = _this.scores(entity,"eraseVelocity" + xyz.toUpperCase());
                            } catch(e) {
                                eraseVelocity[xyz] = {
                                    var: 0
                                }
                            }
                            if (entity?.hasComponent("minecraft:movement")) {
                                return [ xyz, xyz === "y" ? -(entity?.isFalling && !entity?.isSwimming ? 0.37 : 0) : ((eraseVelocity[xyz].var / 100) / Math.pow(10,1)) ]
                            } else {
                                return [ xyz, (eraseVelocity[xyz].var / 100) / Math.pow(10,1) ]
                            }
                        }))
                        let eraseRotation = Object.fromEntries("xy".split("").map(xy => {
                            return [ xy, {var:0} ]
                        }))
                        let rotation = Object.fromEntries("xy".split("").map(xy => {
                            try {
                                eraseRotation[xy] = _this.scores(entity,"eraseRotation" + xy.toUpperCase());
                            } catch(e) {
                                eraseRotation[xy] = {
                                    var: 0
                                }
                            }
                            return [ xy, eraseRotation[xy].var / 100 ]
                        }))
                        if (entity?.hasComponent("minecraft:movement") || entity?.typeId === "minecraft:ender_dragon") {
                            entity?.setRotation(rotation)
                        }
                        if (entity?.typeId === "minecraft:player") {
                            // entity?.applyKnockback(0, 0, 0, -3 * !entity?.isSwimming)
                            if (entity?.isSprinting) {
                                entity?.applyKnockback(0,0,0,entity?.getVelocity().y * 0.65);
                            }
                            for (let effect of [ "slowness->2", "slow_falling->6", "blindness->20", "mining_fatigue->10" ]) {
                                let name = effect.split("->")[0];
                                let amplifier = parseInt(effect.split("->")[1]);
                                entity?.addEffect(name, 20, {
                                    amplifier: amplifier,
                                    showParticles: false
                                });
                            }
                        } else {
                            for (let effect of [ "slow_falling->1", "slowness->4", "mining_fatigue->10" ]) {
                                let name = effect.split("->")[0];
                                let amplifier = parseInt(effect.split("->")[1]);
                                entity?.addEffect(name, 20, {
                                    amplifier: amplifier,
                                    showParticles: false
                                });
                            }
                            entity?.clearVelocity();
                            entity?.applyImpulse(velocity);
                        }
                        let erasePosition = Object.fromEntries("xyz".split("").map(xyz => {
                            return [ xyz, {var: entity?.location[xyz] * 100} ]
                        }))
                        let velocityType = [
                            entity?.getVelocity(),
                            velocity
                        ]
                        "xyz".split("").map(xyz => {
                            try {
                                erasePosition[xyz] = _this.scores(entity,"erasePosition" + xyz.toUpperCase());
                            } catch(e) {
                                erasePosition[xyz] = {
                                    var: entity?.location[xyz] * 100
                                }
                            }
                            // console.error(timeEraseDistance.var)
                            // erasePosition[xyz].var = (Math.round(entity?.location[xyz]) + Mathf.clamp(velocity[xyz]*150,-1,1) * timeEraseDistance.var) * 100
                            erasePosition[xyz].var = (Math.round(entity?.location[xyz]) + Mathf.clamp(velocityType[+(entity?.typeId === "minecraft:player")][xyz]*150,-1,1) * timeEraseDistance.var / 100) * 100
                        })
                        let futurePosition = Object.fromEntries("xyz".split("").map(xyz => {
                            return [ xyz, xyz === "y" ? entity?.location.y : (erasePosition[xyz].var / 100) ]
                        }))
                        let facing = (option) => {
                            let x = parseFloat(option.position1.x + option.position2.x);
                            let y = parseFloat(option.position1.y - option.position2.y);
                            let rot = parseFloat(option.rotation);
                            return 57.2958 * Math.atan2(y,x) + rot;
                            // return 57.2958 * Math.atan2(y,x) * (Math.PI / 180) + rot;
                        };
                        let entityFacing = facing({
                            position1: {
                                x: entity?.location.x,
                                y: entity?.location.z
                            },
                            position2: {
                                x: futurePosition.x,
                                y: futurePosition.z
                            },
                            rotation: rotation.y
                            // rotation: 0
                        })
                        let entityCurrentPosition = Object.fromEntries("xyz".split("").map(xyz => {
                            return [ xyz, entity?.location[xyz]/* + (xyz === "y") * 0.5*/ ]
                        }))
                        let direction = _this.getLc2(0,entityFacing);
                        let getBlockFromVector = entity?.dimension?.getBlockFromRay(entityCurrentPosition,{
                            x: direction.x,
                            y: 0.0,
                            z: direction.z
                        },{
                            includeLiquidBlocks: false,
                            includePassableBlocks: true,
                            maxDistance: 5
                        })
                        let getBlockFromVector2 = entity?.dimension?.getBlockFromRay(entityCurrentPosition,{
                            x: direction.x,
                            y: 0.3,
                            z: direction.z
                        },{
                            includeLiquidBlocks: false,
                            includePassableBlocks: true,
                            maxDistance: 5
                        })
                        if (getBlockFromVector !== undefined || getBlockFromVector2 !== undefined) {
                            let blockPos = "xyz".split("").map(xyz => {
                                return getBlockFromVector?.block[xyz];
                            })
                            let distance = new Vec3(...Object.values(entityCurrentPosition)).Distance(...blockPos);
                            timeEraseDistance.var = (Mathf.clamp(distance,0,5).toFixed(2) - 2) * 100
                            // console.error(getBlockFromVector?.block?.typeId)
                            // console.error(timeEraseDistance.var)
                        } else {
                            timeEraseDistance.var = 300
                        }
                        let test = new mc.MolangVariableMap();
                        if (entity?.hasComponent("minecraft:movement")) {
                            entity?.dimension.spawnParticle("kingcrimson:erase_effect",futurePosition,test)
                            // console.error(timeEraseDistance.var)
                            /*
                            for (let i of range(1,timeEraseDistance.var / 100)) {
                                let testPosition = Object.fromEntries("xyz".split("").map(xyz => {
                                    return [ xyz, entity?.location[xyz] + direction[xyz] * (xyz !== "y") * i ];
                                }))
                                entity?.dimension.spawnParticle("minecraft:villager_happy",testPosition,test)
                            }*/
                            
                        }
                    }
                } else {
                    let eraseRotation = Object.fromEntries("xy".split("").map(xy => {
                        return [ xy, {var:0} ]
                    }))
                    let rotation = Object.fromEntries("xy".split("").map(xy => {
                        try {
                            eraseRotation[xy] = _this.scores(entity,"eraseRotation" + xy.toUpperCase());
                        } catch(e) {
                            eraseRotation[xy] = {
                                var: 0
                            }
                        }
                        return [ xy, eraseRotation[xy].var / 100 ]
                    }))
                    let eraseVelocity = Object.fromEntries("xyz".split("").map(xyz => {
                        return [ xyz, {var:0} ]
                    }))
                    let velocity = Object.fromEntries("xyz".split("").map(xyz => {
                        try {
                            eraseVelocity[xyz] = _this.scores(entity,"eraseVelocity" + xyz.toUpperCase());
                        } catch(e) {
                            eraseVelocity[xyz] = {
                                var: 0
                            }
                        }
                        return [ xyz, eraseVelocity[xyz].var / 100 ]
                    }))
                    let erasePosition = Object.fromEntries("xyz".split("").map(xyz => {
                        return [ xyz, {var: entity?.location[xyz] * 100} ]
                    }))
                    let futurePosition = Object.fromEntries("xyz".split("").map(xyz => {
                        try {
                            erasePosition[xyz] = _this.scores(entity,"erasePosition" + xyz.toUpperCase());
                        } catch(e) {
                            erasePosition[xyz] = {
                                var: entity?.location[xyz] * 100
                            }
                        }
                        return [ xyz, xyz === "y" ? entity?.location.y : (erasePosition[xyz].var / 100) ]
                    }))
                    if (entity?.hasComponent("minecraft:movement")) {
                        entity?.teleport(futurePosition,{
                            rotation: rotation,
                            keepVelocity: entity?.typeId !== "minecraft:player"
                        });
                    } else {
                        entity?.applyImpulse(velocity);
                    }
                    if (entity?.typeId === "minecraft:player") {
                        for (let effect of [ "slow_falling", "slowness", "blindness", "mining_fatigue" ]) {
                            _this.runCommand(`effect @s ${effect} 0 0 true`, entity);
                        }
                    } else {
                        entity?.addEffect("slowness", 20, {
                            amplifier: 10,
                            showParticles: false
                        });
                    }
                    entity?.removeTag("remove.timeErase")
                    entity?.removeTag("entity.in_timeErase")
                }
            })
        },1)
    }
    
    APattack(data) {
        let player = this.standMaster;
        this.slot_data[1].var = [
            this.use_skill1 && player?.isSneaking,
            (this.ap_cd.var / 20).toFixed(1),
            data.cooldown,
            NaN
        ].join("|")
        player?.addTag("stand.can_ap")
        if (!player?.hasTag("stand.APattack") && this.mental_value.var > 0 && this.ap_cd.var >= 0 && this.ap_cd.var < data.cooldown * 20) {
            this.ap_cd.var += 1;
        }
        if (player?.hasTag("stand.APattack") && this.ap_cd.var >= data.cooldown * 20 && this.mental_value.var > 0) {
            this.ap_cd2.var += 1;
            this.removeMentalValue(data.mental);
            this.broadcastAnim("stand->ap");
            if (this.ap_cd2.var == 2) {
                let entityFV = this.getEntitiesFromViewVector(player, data.range + 1).filter(e => e.entity.hasComponent("minecraft:health"))[0];
                if (entityFV !== undefined) {
                    let entity = entityFV?.entity
                    this.set_stand_range2(entity)
                    this.runCommands([
                        `damage @s[type=!ender_dragon,type=!player] 0 suicide`,
                        `damage @s[m=adventure,type=player] 0 suicide`,
                        `damage @s[m=survival,type=player] 0 suicide`,
                        `damage @s[type=ender_dragon] 0 suicide entity @a[name="${player?.name}"]`,
                        `effect @s[type=!player] slowness 2 255 true`,
                        `effect @s[type=player] slowness 1 1 true`,
                        `tag @s remove isAttackedByAP`
                    ], entity);
                    for (let sound of data.sounds) {
                        this.runCommand(`playsound ${sound} @a ~ ~ ~`, entity);
                    }
                    let test = new mc.MolangVariableMap();
                    let entity_pos = "xyz".split("").map(xyz => {
                        return entity.getHeadLocation()[xyz] - (xyz === "y") * 0.3
                    })
                    
                    let health = entity.getComponent("minecraft:health");
                    if (entity?.typeId === "minecraft:player") {
                        if (entity?.hasTag("kingCrimson.epitaph")) {
                            let epitaph_position = this.GlobalVar(entity,"epitaph_position")
                            let epitaph_vector = this.GlobalVar(entity,"epitaph_vector")
                            let entity_pos = "xyz".split("").map(xyz => {
                                return entity?.location[xyz].toFixed(3);
                            })
                            let entity_vec = "xyz".split("").map(xyz => {
                                return this.getLc(entity)[xyz].toFixed(3);
                            })
                            epitaph_position.var = entity_pos.join("|");
                            epitaph_vector.var = entity_vec.join("|");
                            entity?.addTag("kingCrimson.avoid.stand");
                        } else if (!entity?.hasTag("gameMode.creative")) {
                            let shealth = this.GlobalVar(entity,"standMaster.health");
                            let shealth_max = this.GlobalVar(entity,"standMaster.health_max");
                            entity?.dimension.spawnParticle("effect:blood",new Vec3(...entity_pos).Position(),test)
                            if (shealth.var > 0) {
                                shealth.var = Mathf.clamp(shealth.var - data.damage, 0, shealth_max.var);
                                this.runCommand(`damage @s[type=!ender_dragon] 0 suicide`, entity)
                            } else {
                                health.setCurrentValue(health.currentValue - data.damage)
                            }
                        }
                    } else {
                        entity?.dimension.spawnParticle("effect:blood",new Vec3(...entity_pos).Position(),test)
                        health.setCurrentValue(health.currentValue - data.damage);
                    }
                }
                player?.removeTag("stand.APattack");
                this.ap_cd2.var = 0;
                this.ap_cd.var = 0;
            }
        } else if (player?.hasTag("stand.APattack") && this.ap_cd.var < data.cooldown * 20) {
            player?.removeTag("stand.APattack");
        }
        if (!player?.hasTag("stand.APattack")) {
            if (this.ap_cd.var == 3) {
                // this.fist_duration.var = 0;
                // player?.addTag("stand.fist_isCooldown");
                this.removeAnim("stand->ap");
            }
        }
    }
    
    epitaph(data) {
        let player = this.standMaster;
        
        this.slot_data[2].var = [
            (this.use_skill2 && player?.isSneaking) || player?.hasTag("kingCrimson.epitaph"),
            (this.epitaph_tick.var / 20).toFixed(1),
            data.duration,
            NaN
        ].join("|")
        
        if (player?.hasTag("kingCrimson.timeErase")) {
            player?.removeTag("kingCrimson.epitaph");
            // player?.removeTag("kc.epitaph_cooldown");
        }
        
        if (!player?.hasTag("kingCrimson.timeErase") && !player?.hasTag("kc.epitaph_cooldown") && player?.hasTag("kingCrimson.epitaph") && this.mental_value.var > 0 && this.epitaph_tick.var > 0 && this.epitaph_tick.var <= data.duration * 20) {
            this.epitaph_tick.var -= 1;
        }
        if (player?.hasTag("kc.epitaph_cooldown") && this.mental_value.var > 0 && this.epitaph_tick.var >= 0 && this.epitaph_tick.var < data.duration * 20) {
            this.epitaph_tick.var = Mathf.clamp(this.epitaph_tick.var + data.cooldown_reply, 0, data.duration * 20);
            if (this.epitaph_tick.var < data.duration * 20) {
                player?.removeTag("kingCrimson.epitaph")
            }
        }
        if (this.epitaph_tick.var >= data.duration * 20) {
            player?.removeTag("kc.epitaph_cooldown");
        }
        if (!player?.hasTag("kingCrimson.timeErase") && !player?.hasTag("kc.epitaph_cooldown") && player?.hasTag("kingCrimson.epitaph") && this.epitaph_tick.var > 0 && this.mental_value.var > 0) {
            player?.extinguishFire(false)
            let health = player?.getComponent("minecraft:health");
            this.epitaph_tick2.var += 1;
            if (this.epitaph_tick2.var == 1) {
                this.erase_tick.var = 100;
                this.erase_tick2.var = 4;
                player?.addTag("kc.erase_cooldown")
                this.broadcastAnim("king_crimson->epitaph");
                this.LoadingUI2(this.UI.kingCrimson.epitaph);
                this.playerHealth2.var = health?.currentValue + this.shealth.var;
                this.runCommand(`playsound kingCrimson.epitaph @s ~ ~ ~`, player);
                this.MentalPanelUI();
            }
            if (this.epitaph_tick2.var > 1) {
                // health.setCurrentValue(100);
                for (let effect of [ "instant_health", "resistance" ]) {
                    player?.addEffect(effect, 19980, {
                        amplifier: 255,
                        showParticles: false
                    });
                }
                this.delay_tick.var = 0;
                this.runCommand(`tag @e[name=!"${player?.name}",r=3.3] add avoidProjectile`, player);
                this.getEntities({ excludeTypes: [ "xp_orb", "item", "armor_stand", "boat", "minecart" ], tags: [ "avoidProjectile" ], excludeTags: [ "projectile.isHit" ]}).forEach(entity => {
                    if (!entity?.hasComponent("minecraft:movement")) {
                        this.LoadingUI2(this.UI.kingCrimson.skip.default);
                        this.runCommands([
                            `playsound kingCrimson.timeSkip2 @s ~ ~ ~`,
                            `playsound kingCrimson.timeSkip4 @a[tag=kingCrimson.epitaph] ~ ~ ~`
                        ], player);
                        let player_pos = Object.fromEntries("xyz".split("").map(xyz => {
                            return [ xyz, player?.location[xyz] ];
                        }))
                        let entity_pos = Object.fromEntries("xyz".split("").map(xyz => {
                            return [ xyz, entity?.location[xyz] ];
                        }))
                        let entity_eyes_pos = Object.fromEntries("xyz".split("").map(xyz => {
                            return [ xyz, entity?.getHeadLocation()[xyz] - (xyz === "y") * 1.5 ];
                        }))
                        let facing = (option) => {
                            let x = parseFloat(option.position1.x + option.position2.x);
                            let y = parseFloat(option.position1.y - option.position2.y);
                            let rot = parseFloat(option.rotation);
                            return 57.2958 * Math.atan2(y,x) + rot;
                        };
                        let entityFacing = facing({
                            position1: {
                                x: entity?.location.x,
                                y: entity?.location.z
                            },
                            position2: {
                                x: entity?.location.x + Mathf.clamp(entity?.getVelocity().x * 150, -1, 1) * this.epitaph_distance.var,
                                y: entity?.location.z + Mathf.clamp(entity?.getVelocity().z * 150, -1, 1) * this.epitaph_distance.var
                            },
                            rotation: -entity?.getRotation().y
                        })
                        let direction = this.getLc2(0,entityFacing);
                        // entity?.runCommand("say " + entityFacing)
                        let getBlockFromVector = entity?.dimension?.getBlockFromRay(entity_pos,{
                            x: -direction.x,
                            y: Mathf.random(7,9) / 10,
                            z: -direction.z
                        },{
                            includeLiquidBlocks: false,
                            includePassableBlocks: true,
                            maxDistance: 5
                        })
                        if (getBlockFromVector !== undefined && getBlockFromVector?.face === "Up") {
                            let blockPos = "xyz".split("").map(xyz => {
                                return getBlockFromVector?.block[xyz];
                            })
                            let d = new Vec3(...Object.values(entity_pos)).Distance(...blockPos);
                            this.epitaph_distance.var = Math.round(Mathf.clamp(d,0,5)) - 2
                        } else {
                            this.epitaph_distance.var = 3
                        }
                        let player_tp_pos = Object.fromEntries("xyz".split("").map(xyz => {
                            return [ xyz, player_pos[xyz] + (xyz === "y") * 0 - direction[xyz] * (1 - (xyz === "y")) * this.epitaph_distance.var ];
                        }))
                        player?.teleport(player_tp_pos,{
                            rotation: {
                                x: player?.getRotation().x,
                                y: player?.getRotation().y
                            }
                        })
                        // entity?.addTag("projectile.isHit")
                        // entity?.removeTag("avoidProjectile")
                    }
                    entity?.removeTag("avoidProjectile")
                })
                if (player?.hasTag("kingCrimson.avoid.stand")) {
                    this.LoadingUI2(this.UI.kingCrimson.skip.default);
                    this.runCommands([
                        `playsound kingCrimson.timeSkip2 @s ~ ~ ~`,
                        `playsound kingCrimson.timeSkip4 @a[tag=kingCrimson.epitaph] ~ ~ ~`
                    ], player);
                    let target_pos = Object.fromEntries(this.epitaph_position.var.split("|").map((xyz,index) => {
                        return [ "xyz".split("")[index], parseFloat(xyz) ]
                    }));
                    let target_vec = Object.fromEntries(this.epitaph_vector.var.split("|").map((xyz,index) => {
                        return [ "xyz".split("")[index], parseFloat(xyz) ]
                    }));
                    let direction = target_vec;
                    let getBlockFromVector = player?.dimension?.getBlockFromRay(target_pos,{
                        x: -direction.x,
                        y: 0.0,
                        z: -direction.z
                    },{
                        includeLiquidBlocks: false,
                        includePassableBlocks: true,
                        maxDistance: 5
                    })
                    if (getBlockFromVector !== undefined) {
                        let blockPos = "xyz".split("").map(xyz => {
                            return getBlockFromVector?.block[xyz];
                        })
                        let d = new Vec3(...Object.values(target_pos)).Distance(...blockPos);
                        this.epitaph_distance.var = Math.round(Mathf.clamp(d,0,5)) - 2
                    } else {
                        this.epitaph_distance.var = 3
                    }
                    let player_tp_pos = Object.fromEntries("xyz".split("").map(xyz => {
                        return [ xyz, target_pos[xyz] - target_vec[xyz] * (1 - (xyz === "y")) * this.epitaph_distance.var ];
                    }))
                    player?.teleport(player_tp_pos,{
                        facingLocation: target_pos
                    })
                    player?.removeTag("kingCrimson.avoid.stand");
                }
                if (player?.hasTag("kingCrimson.avoid")) {
                    this.LoadingUI2(this.UI.kingCrimson.skip.default);
                    this.runCommands([
                        `playsound kingCrimson.timeSkip2 @s ~ ~ ~`,
                        `playsound kingCrimson.timeSkip4 @a[tag=kingCrimson.epitaph] ~ ~ ~`
                    ], player);
                    this.getEntities({tags:["attackedTarget:" + player?.name]}).forEach(entity => {
                        let entity_pos = Object.fromEntries("xyz".split("").map(xyz => {
                            return [ xyz, entity?.location[xyz] ];
                        }))
                        let entity_eyes_pos = Object.fromEntries("xyz".split("").map(xyz => {
                            return [ xyz, entity?.getHeadLocation()[xyz] - (xyz === "y") * 1.5 ];
                        }))
                        let direction = this.getLc(entity);
                        let getBlockFromVector = entity?.dimension?.getBlockFromRay(entity_pos,{
                            x: -direction.x,
                            y: 0.0,
                            z: -direction.z
                        },{
                            includeLiquidBlocks: false,
                            includePassableBlocks: true,
                            maxDistance: 5
                        })
                        if (getBlockFromVector !== undefined) {
                            let blockPos = "xyz".split("").map(xyz => {
                                return getBlockFromVector?.block[xyz];
                            })
                            let d = new Vec3(...Object.values(entity_pos)).Distance(...blockPos);
                            this.epitaph_distance.var = Math.round(Mathf.clamp(d,0,5)) - 2
                        } else {
                            this.epitaph_distance.var = 3
                        }
                        let player_tp_pos = Object.fromEntries("xyz".split("").map(xyz => {
                            return [ xyz, entity_pos[xyz] - direction[xyz] * (1 - (xyz === "y")) * this.epitaph_distance.var ];
                        }))
                        player?.teleport(player_tp_pos,{
                            facingLocation: entity_eyes_pos
                        })
                        // entity?.removeTag("attackedTarget:" + player?.name)
                        entity?.getTags().filter(tag => tag?.startsWith("attackTarget:")).forEach(tag => {
                            entity?.removeTag(tag)
                        })
                    })
                    
                    player?.removeTag("kingCrimson.avoid");
                }
                if (this.epitaph_tick2.var % data.mental.interval == 0) {
                    this.removeMentalValue(data.mental.value);
                }
            }

        } 
        if ((!player?.hasTag("kingCrimson.epitaph")) || (player?.hasTag("kingCrimson.epitaph") && this.epitaph_tick.var <= 0)) {
            if (this.epitaph_tick2.var > 0) {
                this.runCommand(`effect @s instant_health 0 0 true`, player);
                this.runCommand(`effect @s resistance 0 0 true`, player);
                let health = player?.getComponent("minecraft:health");
                health?.setCurrentValue(this.playerHealth2.var);
                
                this.removeAnim("king_crimson->epitaph");
                this.epitaph_tick2.var = 0;
                
                player?.removeTag("kingCrimson.epitaph");
                player?.removeTag("kingCrimson.avoid");
                player?.addTag("kc.epitaph_cooldown");
            }
        }
        if (!player?.hasTag("kingCrimson.epitaph")) {
            if (this.delay_tick.var >= 0) {
                this.delay_tick.var += 1;
            }
            if (this.delay_tick.var >= 4) {
                this.delay_tick.var = -1;
            }
        }
    }
    
    timeErase(data) {
        let player = this.standMaster;
        let handItem = this.getHandItem(player);
        
        this.slot_data[3].var = [
            (this.use_skill2 && !player?.isSneaking) || player?.hasTag("kingCrimson.timeErase"),
            (this.erase_tick.var / 20).toFixed(1),
            data.duration,
            NaN
        ].join("|")
        
        let cooldown_reply = Mathf.clamp(Math.pow(10,-(Math.floor(this.erase_tick.var/20)/10)).toFixed(1),0.3,1)
        
        if (player?.hasTag("kingCrimson.timeErase") && this.erase_tick.var > 0 && this.erase_tick.var <= data.duration * 20) {
            this.erase_tick.var -= 1;
        }
        if (!player?.hasTag("kingCrimson.timeErase") && this.erase_tick.var >= 0 && this.erase_tick.var < data.duration * 20) {
            this.erase_tick.var = Mathf.clamp(this.erase_tick.var + cooldown_reply, 0, data.duration * 20);
        }

        if (this.erase_tick.var >= data.duration * 20) {
            player?.removeTag("kc.erase_cooldown");
            this.erase_tick2.var = 0;
        }
        
        if (player?.hasTag("kingCrimson.timeErase") && !player?.hasTag("kc.erase_cooldown") && this.mental_value.var > 0) {
            this.erase_tick2.var += 1;
            if (this.erase_tick2.var == 2) {
                this.LoadingUI2(this.UI.kingCrimson.skip.on);
                this.broadcastAnim("king_crimson->time_skip");
                this.effect("saveCurrent");
                this.runCommand(`playsound kingCrimson.timeSkip1 @s ~ ~ ~`, player);
                let health = player?.getComponent("minecraft:health");
                this.playerHealth.var = health?.currentValue + this.shealth.var;
                player?.removeTag("kingCrimson.epitaph")
            }
            if (this.erase_tick2.var == 3) {
                this.broadcastAnim("king_crimson->player_invisibility");
                // this.runCommand(`fog @s push fog:king_crimson king_crimson_fog`, player);
            }
            if (this.erase_tick2.var == 20) {
                this.runCommand(`playsound kingCrimson.timeErase @s ~ ~ ~`, player);
            }
            if (this.erase_tick2.var > 5) {
                this.LoadingUI2(this.UI.kingCrimson.redScreen)
            }
            if (this.erase_tick2.var > 0) {
                this.delay_tick.var = 0;
                player?.extinguishFire(false)
                player?.addTag("kc.doubt");
                player?.addTag("kc.ban_epitaph")
                this.runCommand(`camera @s set minecraft:first_person`, player)
                this.runCommand(`tag @e[tag=!kingCrimson.timeErase,tag=!entity.in_timeErase,r=32] add entity.in_timeErase`, player)
                this.runCommand(`tag @e[tag=isFirstCreated] remove isFirstCreated`, player)
                let health = player?.getComponent("minecraft:health");
                // if (health.currentValue > 99) {
                    // health.setCurrentValue(health.currentValue + 1);
                // }
                player?.addEffect("speed", 40, {
                    amplifier: 2,
                    showParticles: false
                });
                
            }
            if (this.erase_tick2.var % data.mental.interval == 0) {
                this.removeMentalValue(data.mental.value);
            }
            
            if (this.erase_tick2.var % 3 == 0) {
                this.effect("createNew");
            }
            
        }
        if ((player?.hasTag("kingCrimson.timeErase") && this.erase_tick.var <= 0) || this.mental_value.var <= 0) {
            player?.removeTag("kingCrimson.timeErase");
        }
        if ((!player?.hasTag("kingCrimson.timeErase") || (player?.hasTag("kingCrimson.timeErase") && this.erase_tick.var <= 0))) {
            if (player?.hasTag("kc.doubt") && !player?.hasTag("kc.erase_cooldown")) {
                player?.removeTag("kingCrimson.timeErase");
                this.LoadingUI2(this.UI.kingCrimson.skip.off);
                this.runCommand(`tag @e[tag=entity.in_timeErase,tag=!isFirstCreated] add remove.timeErase`, player)
                // this.runCommand(`fog @s remove king_crimson_fog`, player);
                this.runCommand(`playsound kingCrimson.timeSkip2 @s ~ ~ ~`, player);
                this.runCommand(`stopsound @s kingCrimson.timeErase`, player);
                this.runCommand(`effect @s speed 0 0 true`, player);
                if (!player?.hasTag("stand.quick_fist")) {
                    this.removeAnim("king_crimson->time_skip");
                }

                this.epitaph_tick.var = 25;
                this.erase_tick2.var = 0;
                this.effect("remove","clear");
                player?.addTag("kc.erase_cooldown")
            }
        }
        if (player?.hasTag("kc.erase_cooldown")) {
            player?.removeTag("kingCrimson.timeErase")
            this.erase_tick2.var += 1;
            if (this.erase_tick2.var == 2) {
                player?.addTag("kc.epitaph_cooldown");
                this.runCommand(`camera @s clear`, player);
                let health = player?.getComponent("minecraft:health");
                health.setCurrentValue(this.playerHealth.var)
            }
            if (this.erase_tick2.var == 3) {
                player?.removeTag("kc.ban_epitaph")
                this.effect("remove","setCurrent")
            }
            if (this.erase_tick2.var == 4) {
                player?.removeTag("kc.doubt")
                this.erase_tick2.var = 0;
            }
        }
        if (!player?.hasTag("kingCrimson.timeErase")) {
            if (this.delay_tick.var >= 0) {
                this.delay_tick.var += 1;
            }
            if (this.delay_tick.var >= 4) {
                this.delay_tick.var = -1;
            }
        }
    }
    /*
    timeErase(data) {
        let tag = "绯红之王时间删除";
        let player = this.standMaster;
        
        if (player?.hasTag("player?.isSkippingTime") && this.skip_duration > 0) {
            this.playerScores.add(`skip_tick`,`scores={skip_tick=0..10}`,1);
            this.runCommand(`tag @s[scores={skip_tick=10..}] add kingCrimson.erase`, player);
            
            this.testfor(player, `scores={skip_tick=1}`, () => {
                this.effect("saveCurrent");
                this.broadcastAnim("king_crimson->time_skip");
            })
            this.testfor(player, `tag=!kingCrimson.skip,scores={skip_tick=4}`, () => {
                let playerCurrentHealth = `playerHealth_inNotSkippingTime: ${Math.round(this.health.currentValue).toString()}`
                player?.addTag(playerCurrentHealth);
                player?.removeTag("kingCrimson.epitaph");
                player?.removeTag("kingCrimson.epitaph2");
                let fake_player = player?.dimension.spawnEntity("kingcrimson:fake_player", new Vec3(player?.location.x, player?.location.y, player?.location.z).Position());
                fake_player?.nameTag = player?.name;
                fake_player?.setRotation(-player?.rotation.x, player?.rotation.y);
                this.runCommands([
                    `playsound kingCrimson.timeSkip1 @s ~ ~ ~`,
                    `tag @e[type=!player,r=23] add entity.inSkippingTime`,
                    `fog @s push stand:crimson_fog king_crimson_fog`,
                    `tag @s add kingCrimson.skip`
                ], player);
                this.broadcastAnim("king_crimson->player_invisibility");
                this.LoadingUI(this.UI.kingCrimson.skip.on);
            });
            this.testfor(player, `tag=kingCrimson.erase`, () => {
                player?.removeTag("kingCrimson.epitaph");
                player?.removeTag("kingCrimson.epitaph2");
                this.playerScores.remove("skip_duration", `scores={skip_duration=1..${data.duration * 20}}`, 1);
                this.health.setCurrentValue(Math.min(this.health.currentValue * 10, Math.round(Mathf.random(2000, 3000))));
                this.LoadingUI(this.UI.kingCrimson.redScreen);
                this.effect("createNew");
                this.playerScores.add(`skip_tick2`,`scores={skip_tick2=0..10}`,1)
                this.runCommands([
                    `playsound kingCrimson.timeErase @s[scores={skip_tick2=8}] ~ ~ ~`,
                    "tag @s[scores={skip_duration=0}] remove player?.isSkippingTime"
                ], player);
                let setEntitiesTarget = this.setEntitiesTargetInSkippingTime(
                    {
                        type: "kingcrimson:fake_player"
                    },
                    {
                        excludeTypes: [ "kingcrimson:fake_player", "item" ],
                        families: [ "monster" ],
                        tags: [ "entity.inSkippingTime" ]
                    },
                    {
                        excludeTypes: [ "kingcrimson:fake_player", "item" ],
                        families: [ "mob" ],
                        tags: [ "entity.inSkippingTime" ]
                    }
                )
            });
        }
        if (!player?.hasTag("player?.isSkippingTime")) {
            this.testfor(player, `tag=kingCrimson.skip`, () => {
                this.LoadingUI(this.UI.kingCrimson.skip.off);
                this.movement.resetToDefaultValue();
                this.removeAnim("king_crimson->time_skip",`scores={ap_cooldown=0..60}`);
                this.runCommands([
                    `event entity @e[name="${player?.name}"] despawn`,
                    `playsound kingCrimson.timeSkip2 @s ~ ~ ~`,
                    `playsound kingCrimson.timeSkip4 @a[tag=kingCrimson.skip] ~ ~ ~`,
                    `tag @e[type=!player] remove entity.inSkippingTime`,
                    `tag @s remove kingCrimson.skip`,
                    `tag @s[tag=kingCrimson.erase] remove kingCrimson.erase`,
                    `fog @s remove king_crimson_fog`
                ], player);
                player?.getTags().filter(tags => tags.includes("playerHealth_inNotSkippingTime")).forEach(playerDefaultHealth => {
                    let health = parseInt(playerDefaultHealth.split(": ")[1]);
                    this.health.setCurrentValue(health);
                    if (player?.hasTag(playerDefaultHealth)) {
                        player?.removeTag(playerDefaultHealth);
                    }
                });
                this.playerScores.set(`skip_tick`,0);
                this.playerScores.set(`skip_tick2`,0);
            });
            if (!player?.isSneaking) {
                this.playerScores.add("skip_duration", `scores={skip_duration=0..${data.duration * 20 - 1}}`, 1);
            }
            this.effect("remove");
        }
    }
    */
    
    effect(mode,type) {
        let player = this.standMaster;
        let effectList = {
            effect1: new Array("levitation", "wither", "slowness", "blindness", "poison", "fatal_poison", "hunger", "nausea"),
            effect2: new Array("mining_fatigue", "invisibility", "weakness", "resistance", "fire_resistance", "conduit_power", "instant_health"),
            effect3: new Array("jump_boost", "slow_falling"),
            effect4: new Array("darkness")
        }
        let saveEffect = (effect) => {
            effectList[effect].forEach(value => {
                let getEffect = () => {
                    if (value.includes("_")) {
                        return this.standMaster.getEffect(value);
                    } else {
                        return this.standMaster.getEffect(value);
                    }
                }
                if (getEffect() !== undefined) {
                    player?.addTag(`effect:${value}-${Math.round(this.getTimer(getEffect().duration))}-${getEffect().amplifier}`);
                }
            });
        }
        let addEffect = (effect,duration,amplifier) => {
            effectList[effect].forEach(value => {
                if (value.includes("_")) {
                    return this.standMaster.addEffect(value,duration*20,{
                        amplifier: amplifier,
                        showParticles: false
                    });
                } else {
                    return this.standMaster.addEffect(value,duration*20,{
                        amplifier: amplifier,
                        showParticles: false
                    });
                }
            });
        }
        switch (mode) {
            case "saveCurrent":
                saveEffect("effect1");
                saveEffect("effect2");
                saveEffect("effect3");
                saveEffect("effect4");
                break;
            case "createNew":
                effectList.effect1.forEach(value => {
                    this.runCommand(`effect @s ${value} 0 0 true`, player)
                });
                addEffect("effect2",9999,255)
                addEffect("effect3",9999,2)
                addEffect("effect4",9999,1)
                break;
            case "remove":
                switch (type) {
                    case "clear":
                        effectList.effect2.forEach(value => {
                            this.runCommand(`effect @s ${value} 0 0 true`, player)
                        });
                        effectList.effect3.forEach(value => {
                            this.runCommand(`effect @s ${value} 0 0 true`, player)
                        });
                        effectList.effect4.forEach(value => {
                            this.runCommand(`effect @s ${value} 0 0 true`, player)
                        });
                        break;
                    case "setCurrent":
                        player?.getTags().filter(tags => tags.includes("effect:")).forEach(effects =>{
                            let effect = {
                                name: effects.replace(/effect:/g, "").split("-")[0],
                                duration: parseInt(effects.replace(/effect:/g, "").split("-")[1]),
                                amplifier: parseInt(effects.replace(/effect:/g, "").split("-")[2])
                            }
                            this.runCommand(`effect @s ${effect.name} ${effect.duration} ${effect.amplifier}`, player);
                            if (player?.hasTag(effects)) {
                                player?.removeTag(effects)
                            }
                        })
                        break;
                }
                break;
        }
    }
    
}

