// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.server.npc.corecomponents.combat;

import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.server.core.modules.physics.util.PhysicsMath;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.server.npc.movement.Steering;
import com.hypixel.hytale.component.Store;
import javax.annotation.Nullable;
import com.hypixel.hytale.server.npc.sensorinfo.InfoProvider;
import com.hypixel.hytale.server.npc.role.Role;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.server.npc.corecomponents.builders.BuilderBodyMotionBase;
import com.hypixel.hytale.server.npc.asset.builder.BuilderSupport;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.npc.corecomponents.combat.builders.BuilderBodyMotionAimCharge;
import com.hypixel.hytale.server.npc.movement.controllers.ProbeMoveData;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.server.npc.util.AimingData;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.server.npc.corecomponents.BodyMotionBase;

public class BodyMotionAimCharge extends BodyMotionBase
{
    protected static final ComponentType<EntityStore, TransformComponent> TRANSFORM_COMPONENT_TYPE;
    protected final double relativeTurnSpeed;
    protected final AimingData aimingData;
    protected final Vector3d direction;
    protected final ProbeMoveData probeMoveData;
    
    public BodyMotionAimCharge(@Nonnull final BuilderBodyMotionAimCharge builder, @Nonnull final BuilderSupport support) {
        super(builder);
        this.aimingData = new AimingData();
        this.direction = new Vector3d();
        this.probeMoveData = new ProbeMoveData();
        this.relativeTurnSpeed = builder.getRelativeTurnSpeed(support);
    }
    
    @Override
    public void preComputeSteering(@Nonnull final Ref<EntityStore> ref, @Nonnull final Role role, @Nullable final InfoProvider sensorInfo, @Nonnull final Store<EntityStore> store) {
        if (sensorInfo == null) {
            return;
        }
        sensorInfo.passExtraInfo(this.aimingData);
    }
    
    @Override
    public boolean computeSteering(@Nonnull final Ref<EntityStore> ref, @Nonnull final Role role, @Nullable final InfoProvider sensorInfo, final double dt, @Nonnull final Steering desiredSteering, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        if (sensorInfo == null || !sensorInfo.getPositionProvider().providePosition(this.direction)) {
            desiredSteering.clear();
            return true;
        }
        if (this.aimingData.isHaveAttacked()) {
            if (role.getCombatSupport().isExecutingAttack()) {
                desiredSteering.clear();
                return true;
            }
            this.aimingData.setHaveAttacked(false);
        }
        final Vector3d selfPosition = componentAccessor.getComponent(ref, BodyMotionAimCharge.TRANSFORM_COMPONENT_TYPE).getPosition();
        final double distanceToTarget = role.getActiveMotionController().waypointDistance(selfPosition, this.direction);
        if (distanceToTarget > this.aimingData.getChargeDistance()) {
            this.aimingData.clearSolution();
            return true;
        }
        this.direction.subtract(selfPosition);
        this.direction.setLength(this.aimingData.getChargeDistance());
        final double x = this.direction.getX();
        final double y = this.direction.getY();
        final double z = this.direction.getZ();
        final float yaw = PhysicsMath.normalizeTurnAngle(PhysicsMath.headingFromDirection(x, z));
        final float pitch = PhysicsMath.pitchFromDirection(x, y, z);
        desiredSteering.setYaw(yaw);
        desiredSteering.setPitch(pitch);
        desiredSteering.setRelativeTurnSpeed(this.relativeTurnSpeed);
        final TransformComponent transformComponent = componentAccessor.getComponent(ref, BodyMotionAimCharge.TRANSFORM_COMPONENT_TYPE);
        final Vector3f bodyRotation = transformComponent.getRotation();
        this.aimingData.setOrientation(yaw, pitch);
        if (!this.aimingData.isOnTarget(bodyRotation.getYaw(), bodyRotation.getPitch(), this.aimingData.getDesiredHitAngle())) {
            this.aimingData.clearSolution();
            return true;
        }
        final double distance = role.getActiveMotionController().probeMove(ref, selfPosition, this.direction, this.probeMoveData, componentAccessor);
        if (distance < distanceToTarget - 1.0E-6) {
            this.aimingData.clearSolution();
            return true;
        }
        final Ref<EntityStore> target = sensorInfo.getPositionProvider().getTarget();
        this.aimingData.setTarget(target);
        return true;
    }
    
    static {
        TRANSFORM_COMPONENT_TYPE = TransformComponent.getComponentType();
    }
}
