UNPKG

minecrafthawkeye

Version:

Minecraft bot for equations when shooting an arrow

261 lines (242 loc) 10 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _types = require("./types"); var _vec = require("vec3"); var _intercept = require("./intercept"); var _loadBot = require("./loadBot"); var _constants = require("./constants"); var _mathHelper = require("./mathHelper"); // // TODO: Pending to remove these global variables // let target: Entity | OptionsMasterGrade // let speed: Vec3 // let startPosition: Vec3 // let targetPosition: Vec3 // let BaseVo: number // Power of shot, Depends of weapon have different value // let GRAVITY: number // Depends of weapon have different gravity const getMasterGrade = (targetIn, speedIn, weapon) => { if (!Object.keys(_types.Weapons).includes(weapon)) { throw new Error(`${weapon} is not valid weapon for calculate the grade!`); } const weaponProp = _types.weaponsProps[weapon]; const BaseVo = weaponProp.BaseVo; const GRAVITY = weaponProp.GRAVITY; const target = targetIn; const speed = speedIn; const startPosition = _loadBot.bot.entity.position.offset(0, 1.6, 0); // Bow offset position // Calculate target Height, for shot in the heart =P const targetHeight = !(0, _types.isEntity)(target) ? 0 : target.type === 'player' ? 1.16 : target.height ?? 0; const targetPosition = target.position.offset(0, targetHeight, 0); // Check the first best trayectory let distances = (0, _mathHelper.getTargetDistance)(startPosition, targetPosition); let shotCalculation = geBaseCalculation(distances.hDistance, distances.yDistance, GRAVITY, startPosition, targetPosition, BaseVo); if (!shotCalculation) { return undefined; } // Recalculate the new target based on speed + first trayectory const premonition = getPremonition(shotCalculation.totalTicks, speed, startPosition, targetPosition); distances = premonition.distances; const newTarget = premonition.newTarget; // Recalculate the trayectory based on new target location shotCalculation = geBaseCalculation(distances.hDistance, distances.yDistance, GRAVITY, startPosition, targetPosition, BaseVo); if (!shotCalculation) { return undefined; } // Get more precision on shot const precisionShot = getPrecisionShot(shotCalculation.grade, distances.hDistance, distances.yDistance, 1, GRAVITY, startPosition, targetPosition, BaseVo); const { arrowTrajectoryPoints, blockInTrayect, nearestDistance, nearestGrade } = precisionShot; // Calculate yaw const yaw = (0, _mathHelper.calculateYaw)(startPosition, newTarget); if (nearestDistance > 4) { return undefined; } // Too far return { pitch: (0, _mathHelper.degreesToRadians)(nearestGrade / 10), yaw, grade: nearestGrade / 10, nearestDistance, target: newTarget, arrowTrajectoryPoints, blockInTrayect }; }; // Simulate Arrow Trayectory const tryGrade = (grade, xDestination, yDestination, VoIn, tryIntercetpBlock = false, GRAVITY, startPosition, targetPosition) => { let precisionFactor = 1; // !Danger More precision increse the calc! => !More Slower! let Vo = VoIn; let gravity = GRAVITY / precisionFactor; let factorY = _constants.FACTOR_Y / precisionFactor; let factorH = _constants.FACTOR_H / precisionFactor; // Vo => Vector total velocity (X,Y,Z) // For arrow trayectory only need the horizontal discante (X,Z) and verticla (Y) let Voy = (0, _mathHelper.getVoy)(Vo, (0, _mathHelper.degreesToRadians)(grade)); // Vector Y let Vox = (0, _mathHelper.getVox)(Vo, (0, _mathHelper.degreesToRadians)(grade)); // Vector X let Vy = Voy / precisionFactor; let Vx = Vox / precisionFactor; let Alfa; let nearestDistance; let totalTicks = 0; let blockInTrayect = null; const arrowTrajectoryPoints = []; arrowTrajectoryPoints.push(startPosition); const yaw = (0, _mathHelper.calculateYaw)(startPosition, targetPosition); while (true) { const firstDistance = Math.sqrt(Math.pow(Vy - yDestination, 2) + Math.pow(Vx - xDestination, 2)); if (nearestDistance === undefined) { nearestDistance = firstDistance; } if (firstDistance < nearestDistance) { nearestDistance = firstDistance; } // Increse precission when arrow is near over target, // Dynamic Precission, when arrow is near target increse * the precission !Danger with this number if (nearestDistance < 4) { precisionFactor = 5; } if (nearestDistance > 4) { precisionFactor = 1; } totalTicks += 1 / precisionFactor; gravity = GRAVITY / precisionFactor; factorY = _constants.FACTOR_Y / precisionFactor; factorH = _constants.FACTOR_H / precisionFactor; Vo = (0, _mathHelper.getVo)(Vox, Voy, gravity); Alfa = (0, _mathHelper.applyGravityToVoy)(Vo, Voy, gravity); Voy = (0, _mathHelper.getVoy)(Vo, Alfa, Voy * factorY); Vox = (0, _mathHelper.getVox)(Vo, Alfa, Vox * factorH); Vy += Voy / precisionFactor; Vx += Vox / precisionFactor; const x = startPosition.x - Math.sin(yaw) * Vx; const z = yaw === 0 ? startPosition.z : startPosition.z - Math.sin(yaw) * Vx / Math.tan(yaw); const y = startPosition.y + Vy; const currentArrowPosition = new _vec.Vec3(x, y, z); arrowTrajectoryPoints.push(currentArrowPosition); const previusArrowPositionIntercept = arrowTrajectoryPoints[arrowTrajectoryPoints.length === 1 ? 0 : arrowTrajectoryPoints.length - 2]; if (tryIntercetpBlock) { blockInTrayect = (0, _intercept.check)(previusArrowPositionIntercept, currentArrowPosition); } // Arrow passed player || Voy (arrow is going down and passed player) || Detected solid block if (Vx > xDestination || Voy < 0 && yDestination > Vy || blockInTrayect !== null) { return { nearestDistance, totalTicks, blockInTrayect, arrowTrajectoryPoints }; } } }; // Get more precision on shot const getPrecisionShot = (grade, xDestination, yDestination, decimals, GRAVITY, startPosition, targetPosition, BaseVo) => { let nearestDistance; let nearestGrade; let arrowTrajectoryPoints; let blockInTrayect = null; decimals = Math.pow(10, decimals); for (let iGrade = grade * 10 - 10; iGrade <= grade * 10 + 10; iGrade += 1) { const distance = tryGrade(iGrade / decimals, xDestination, yDestination, BaseVo, true, GRAVITY, startPosition, targetPosition); if (nearestDistance === undefined || distance.nearestDistance < nearestDistance) { nearestDistance = distance.nearestDistance; nearestGrade = iGrade; arrowTrajectoryPoints = distance.arrowTrajectoryPoints; blockInTrayect = distance.blockInTrayect; } } if (nearestDistance === undefined || nearestGrade === undefined || arrowTrajectoryPoints === undefined) { throw Error('Error con calc getPrecisionShot'); } return { nearestGrade, nearestDistance, arrowTrajectoryPoints, blockInTrayect }; }; // Calculate all 180º first grades // Calculate the 2 most aproax shots // https://es.qwe.wiki/wiki/Trajectory const getFirstGradeAproax = (xDestination, yDestination, GRAVITY, startPosition, targetPosition, BaseVo) => { let firstFound = false; let nearestGradeFirst; let nearestGradeSecond; for (let grade = -89; grade < 90; grade++) { const calculatedTryGrade = tryGrade(grade, xDestination, yDestination, BaseVo, false, GRAVITY, startPosition, targetPosition); const tryGradeShot = { ...calculatedTryGrade, grade }; if (tryGradeShot.nearestDistance > 4) { continue; } if (nearestGradeFirst === undefined) { nearestGradeFirst = tryGradeShot; } if (nearestGradeSecond === undefined) { nearestGradeSecond = tryGradeShot; } if (tryGradeShot.grade - nearestGradeFirst.grade > 10 && firstFound === false) { firstFound = true; nearestGradeSecond = tryGradeShot; } if (nearestGradeFirst.nearestDistance > tryGradeShot.nearestDistance && firstFound === false) { nearestGradeFirst = tryGradeShot; } if (nearestGradeSecond.nearestDistance > tryGradeShot.nearestDistance && firstFound) { nearestGradeSecond = tryGradeShot; } } if (nearestGradeFirst === undefined && nearestGradeSecond === undefined) { return false; } if (nearestGradeFirst === undefined || nearestGradeSecond === undefined) { throw Error('Error on calculate getFirstGradeAproax'); } return { nearestGradeFirst, nearestGradeSecond }; }; const getPremonition = (totalTicks, targetSpeed, startPosition, targetPosition) => { totalTicks = totalTicks + Math.ceil(totalTicks / 10); const velocity = targetSpeed.clone(); const newTarget = targetPosition.clone(); for (let i = 1; i <= totalTicks; i++) { newTarget.add(velocity); } const distances = (0, _mathHelper.getTargetDistance)(startPosition, newTarget); return { distances, newTarget }; }; // For parabola of Y you have 2 times for found the Y position if Y original are downside of Y destination const geBaseCalculation = (xDestination, yDestination, GRAVITY, startPosition, targetPosition, BaseVo) => { const grade = getFirstGradeAproax(xDestination, yDestination, GRAVITY, startPosition, targetPosition, BaseVo); let gradeShot; if (!grade) { return false; } // No aviable trayectory // Check blocks in trayectory const checkFirst = tryGrade(grade.nearestGradeFirst.grade, xDestination, yDestination, BaseVo, true, GRAVITY, startPosition, targetPosition); if (!checkFirst.blockInTrayect && checkFirst.nearestDistance < 4) { gradeShot = grade.nearestGradeFirst; } else { if (!grade.nearestGradeSecond) { return false; // No aviable trayectory } const checkSecond = tryGrade(grade.nearestGradeSecond.grade, xDestination, yDestination, BaseVo, true, GRAVITY, startPosition, targetPosition); if (checkSecond.blockInTrayect) { return false; // No aviable trayectory } gradeShot = grade.nearestGradeSecond; } return gradeShot; }; var _default = exports.default = getMasterGrade;