sefirosweb / minecraftHawkEye

Minecraft bot for equations when shooting an arrow
27 stars 3 forks source link

Add a way to check targets #3

Closed Bottinator22 closed 3 years ago

Bottinator22 commented 4 years ago

I'd love to use this for something, but I can't seem to find any way to check what target the bot currently has or change the target to another.

This would be a pretty nice feature for this plugin, would help a lot with combat since currently my own bots are easily defeated by a bow and cannot use them either.

sefirosweb commented 4 years ago

Hi Bottinator, well they can't return target info, but you have 2 ways to use this bot,

You bot need insert the target for attack,

// target must have position + isValid = true
bot.hawkEye.autoAttack(target)
// For force stop 
bot.hawkEye.stop()

The second method you can "get" the pitch & yaw you need to hit the target, I use this complex bot

// target must have position + isValid = true
// Speed you need calculate XYZ speed of target, for calc exactly where to shot 
const infoShot = bot.hawkEye.getMasterGrade(target, speed) 

see example speed: speed

I hope that help you

Bottinator22 commented 3 years ago

should've clarified what I meant, I took a look at the code and it seems .autoAttack can't be executed frequently, nor can stop

I'd like to check if the bot is currently targeting an entity before trying to use .autoAttack on them

sefirosweb commented 3 years ago

Well you must check first before use auto attack,

This bot only get the perfect Grade for shot to XYZ position, think that this plugin should be something basic to use in any case, the rest of the needs must be solved with mineflayer

If you have an complex bot i recomend you bot.hawkEye.getMasterGrade function instead autoattack, but you need use manually "activate" and / "deactivate" item

SinanAkkoyun commented 3 years ago

I think he means and that is what I am asking myself:

Is there a function that returns if the bot is currently pulling the bow and is in the process of shooting?

Because we want to set the target every physicsTick!

sefirosweb commented 3 years ago

Hi Sinan, I don't have this function, I recommend that you only use the function: hawkEye.get MasterGrade() to get the degrees you need for the shot, The rest you can do it yourself as you want

sefirosweb commented 3 years ago

You can see how works autoattack and it gets in each physicTick the grades and pitch

https://github.com/sefirosweb/minecraftHawkEye/blob/master/src/hawkEye.js



let target
let bot
let preparingShot
let preparingShotTime
let prevPlayerPositions = []
let oneShot
let weapon = 'bow'

function load(botToLoad) {
  bot = botToLoad
}

function autoAttack(targetToAttack, inputWeapon = 'bow', isOneShot = false) {
  if (!targetToAttack) {
    return false
  }
  oneShot = isOneShot

  target = targetToAttack
  preparingShot = false
  prevPlayerPositions = []
  weapon = inputWeapon

  bot.on('physicTick', autoCalc)
  return true
}

function stop() {
  bot.deactivateItem()
  bot.removeListener('physicTick', autoCalc)
}

function autoCalc() {
  let waitTime = 1200 // bow
  if (weapon === 'crossbow') {
    waitTime = 1300
  }

  if (target === undefined || target === false || !target.isValid) {
    stop()
    return false
  }

  if (prevPlayerPositions.length > 10) { prevPlayerPositions.shift() }

  const position = {
    x: target.position.x,
    y: target.position.y,
    z: target.position.z
  }

  prevPlayerPositions.push(position)

  const speed = {
    x: 0,
    y: 0,
    z: 0
  }

  for (let i = 1; i < prevPlayerPositions.length; i++) {
    const pos = prevPlayerPositions[i]
    const prevPos = prevPlayerPositions[i - 1]
    speed.x += pos.x - prevPos.x
    speed.y += pos.y - prevPos.y
    speed.z += pos.z - prevPos.z
  }

  speed.x = speed.x / prevPlayerPositions.length
  speed.y = speed.y / prevPlayerPositions.length
  speed.z = speed.z / prevPlayerPositions.length

  if (!preparingShot) {
    bot.activateItem()
    preparingShot = true
    preparingShotTime = Date.now()
  }

  const infoShot = getMasterGrade(bot, target, speed, weapon)

  if (infoShot) {
    bot.look(infoShot.yaw, infoShot.pitch)

    const currentTime = Date.now()
    if (preparingShot && currentTime - preparingShotTime > waitTime) {
      if (weapon === 'bow') {
        bot.deactivateItem()
      }

      if (weapon === 'crossbow') {
        if ( // Pending to fix check crossbow ready
          bot.heldItem.nbt.value.ChargedProjectiles &&
          bot.heldItem.nbt.value.ChargedProjectiles.value.value[0] &&
          bot.heldItem.nbt.value.ChargedProjectiles.value.value[0].id.value
        ) { // Detects if crossbow is charged
          bot.activateItem()
        } else {
          // Disable click for charge the bow
          bot.deactivateItem()
          return // Wait until next physicTick for shot
        }
      }

      preparingShot = false
      if (oneShot) {
        stop()
      }
    }
  }
}

module.exports = {
  load,
  autoAttack,
  stop
}