feat(skill): combat
This commit is contained in:
@@ -1,24 +1,30 @@
|
||||
import type { Entity } from 'prismarine-entity'
|
||||
import type { Item } from 'prismarine-item'
|
||||
import type { SkillContext } from './base'
|
||||
import pathfinderModel from 'mineflayer-pathfinder'
|
||||
import * as world from '../composables/world'
|
||||
import * as mc from '../utils/mcdata'
|
||||
import { log } from './base'
|
||||
|
||||
/**
|
||||
* Equip the item with highest attack damage
|
||||
*/
|
||||
const { goals } = pathfinderModel
|
||||
|
||||
interface WeaponItem extends Item {
|
||||
attackDamage: number
|
||||
}
|
||||
|
||||
async function equipHighestAttack(ctx: SkillContext): Promise<void> {
|
||||
const { bot } = ctx
|
||||
const weapons = bot.inventory.items().filter(item =>
|
||||
item.name.includes('sword')
|
||||
|| (item.name.includes('axe') && !item.name.includes('pickaxe')),
|
||||
)
|
||||
) as WeaponItem[]
|
||||
|
||||
if (weapons.length === 0) {
|
||||
const tools = bot.inventory.items().filter(item =>
|
||||
item.name.includes('pickaxe')
|
||||
|| item.name.includes('shovel'),
|
||||
)
|
||||
) as WeaponItem[]
|
||||
|
||||
if (tools.length === 0)
|
||||
return
|
||||
|
||||
@@ -35,16 +41,13 @@ async function equipHighestAttack(ctx: SkillContext): Promise<void> {
|
||||
await bot.equip(weapon, 'hand')
|
||||
}
|
||||
|
||||
/**
|
||||
* Attack the nearest mob of the given type
|
||||
*/
|
||||
export async function attackNearest(
|
||||
ctx: SkillContext,
|
||||
mobType: string,
|
||||
kill = true,
|
||||
): Promise<boolean> {
|
||||
const { bot } = ctx
|
||||
const mob = world.getNearbyEntities(bot, 24).find(entity => entity.name === mobType)
|
||||
const worldCtx = world.createWorldContext(ctx.botCtx)
|
||||
const mob = world.getNearbyEntities(worldCtx, 24).find(entity => entity.name === mobType)
|
||||
|
||||
if (mob) {
|
||||
return await attackEntity(ctx, mob, kill)
|
||||
@@ -54,9 +57,6 @@ export async function attackNearest(
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Attack a specific entity
|
||||
*/
|
||||
export async function attackEntity(
|
||||
ctx: SkillContext,
|
||||
entity: Entity,
|
||||
@@ -68,14 +68,16 @@ export async function attackEntity(
|
||||
|
||||
if (!kill) {
|
||||
if (bot.entity.position.distanceTo(pos) > 5) {
|
||||
await bot.pathfinder.goto(bot.pathfinder.goals.GoalNear(pos.x, pos.y, pos.z, 4))
|
||||
const goal = new goals.GoalNear(pos.x, pos.y, pos.z, 4)
|
||||
await bot.pathfinder.goto(goal)
|
||||
}
|
||||
await bot.attack(entity)
|
||||
return true
|
||||
}
|
||||
|
||||
bot.pvp.attack(entity)
|
||||
while (world.getNearbyEntities(bot, 24).includes(entity)) {
|
||||
const worldCtx = world.createWorldContext(ctx.botCtx)
|
||||
while (world.getNearbyEntities(worldCtx, 24).includes(entity)) {
|
||||
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||
if (ctx.shouldInterrupt) {
|
||||
bot.pvp.stop()
|
||||
@@ -87,13 +89,11 @@ export async function attackEntity(
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Defend against nearby hostile mobs
|
||||
*/
|
||||
export async function defendSelf(ctx: SkillContext, range = 9): Promise<boolean> {
|
||||
const { bot } = ctx
|
||||
let attacked = false
|
||||
let enemy = world.getNearestEntityWhere(bot, entity => mc.isHostile(entity), range)
|
||||
const worldCtx = world.createWorldContext(ctx.botCtx)
|
||||
let enemy = world.getNearestEntityWhere(worldCtx, entity => mc.isHostile(entity), range)
|
||||
|
||||
while (enemy) {
|
||||
await equipHighestAttack(ctx)
|
||||
@@ -101,17 +101,17 @@ export async function defendSelf(ctx: SkillContext, range = 9): Promise<boolean>
|
||||
if (bot.entity.position.distanceTo(enemy.position) >= 4
|
||||
&& enemy.name !== 'creeper' && enemy.name !== 'phantom') {
|
||||
try {
|
||||
await bot.pathfinder.goto(bot.pathfinder.goals.GoalFollow(enemy, 3.5), true)
|
||||
const goal = new goals.GoalFollow(enemy, 3.5)
|
||||
await bot.pathfinder.goto(goal)
|
||||
}
|
||||
catch { /* might error if entity dies, ignore */ }
|
||||
}
|
||||
|
||||
if (bot.entity.position.distanceTo(enemy.position) <= 2) {
|
||||
try {
|
||||
const invertedGoal = bot.pathfinder.goals.GoalInvert(
|
||||
bot.pathfinder.goals.GoalFollow(enemy, 2),
|
||||
)
|
||||
await bot.pathfinder.goto(invertedGoal, true)
|
||||
const followGoal = new goals.GoalFollow(enemy, 2)
|
||||
const invertedGoal = new goals.GoalInvert(followGoal)
|
||||
await bot.pathfinder.goto(invertedGoal)
|
||||
}
|
||||
catch { /* might error if entity dies, ignore */ }
|
||||
}
|
||||
@@ -119,7 +119,7 @@ export async function defendSelf(ctx: SkillContext, range = 9): Promise<boolean>
|
||||
bot.pvp.attack(enemy)
|
||||
attacked = true
|
||||
await new Promise(resolve => setTimeout(resolve, 500))
|
||||
enemy = world.getNearestEntityWhere(bot, entity => mc.isHostile(entity), range)
|
||||
enemy = world.getNearestEntityWhere(worldCtx, entity => mc.isHostile(entity), range)
|
||||
|
||||
if (ctx.shouldInterrupt) {
|
||||
bot.pvp.stop()
|
||||
|
||||
Reference in New Issue
Block a user