All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.nukkit.entity.ai.executor.MeleeAttackExecutor Maven / Gradle / Ivy

There is a newer version: 1.20.40-r1
Show newest version
package cn.nukkit.entity.ai.executor;

import cn.nukkit.Player;
import cn.nukkit.Server;
import cn.nukkit.api.PowerNukkitXOnly;
import cn.nukkit.api.Since;
import cn.nukkit.entity.Entity;
import cn.nukkit.entity.EntityCanAttack;
import cn.nukkit.entity.EntityIntelligent;
import cn.nukkit.entity.ai.memory.MemoryType;
import cn.nukkit.event.entity.EntityDamageByEntityEvent;
import cn.nukkit.event.entity.EntityDamageEvent;
import cn.nukkit.inventory.EntityInventoryHolder;
import cn.nukkit.item.Item;
import cn.nukkit.item.MinecraftItemID;
import cn.nukkit.item.enchantment.Enchantment;
import cn.nukkit.math.Vector3;
import cn.nukkit.network.protocol.EntityEventPacket;

import java.util.EnumMap;
import java.util.Map;

/**
 * 通用近战攻击执行器.
 * 

* Universal melee attack actuator. */ @PowerNukkitXOnly @Since("1.6.0.0-PNX") public class MeleeAttackExecutor implements EntityControl, IBehaviorExecutor { protected MemoryType memory; protected float speed; protected int maxSenseRangeSquared; protected boolean clearDataWhenLose; protected int coolDown; protected int attackTick; protected Vector3 oldTarget; /** * 用来指定特定的攻击目标. *

* Used to specify a specific attack target. */ @Since("1.19.30-r1") protected Entity target; /** * 用来指定特定的视线目标 *

* Used to specify a specific look target. */ @Since("1.19.30-r1") protected Vector3 lookTarget; /** * 近战攻击执行器 * * @param memory 记忆 * @param speed 移动向攻击目标的速度 * @param maxSenseRange 最大获取攻击目标范围 * @param clearDataWhenLose 失去目标时清空记忆 * @param coolDown 攻击冷却时间(单位tick) */ public MeleeAttackExecutor(MemoryType memory, float speed, int maxSenseRange, boolean clearDataWhenLose, int coolDown) { this.memory = memory; this.speed = speed; this.maxSenseRangeSquared = maxSenseRange * maxSenseRange; this.clearDataWhenLose = clearDataWhenLose; this.coolDown = coolDown; } @Override public boolean execute(EntityIntelligent entity) { attackTick++; if (!entity.isEnablePitch()) entity.setEnablePitch(true); if (this.target == null) { //获取目标 if (entity.getBehaviorGroup().getMemoryStorage().isEmpty(memory)) return false; target = entity.getBehaviorGroup().getMemoryStorage().get(memory); } //如果是玩家检测模式 检查距离 检查是否在同一维度 if ((target instanceof Player player && !player.isSurvival()) || entity.distanceSquared(target) > maxSenseRangeSquared || !entity.level.getName().equals(target.level.getName())) return false; if (entity.getMovementSpeed() != speed) entity.setMovementSpeed(speed); if (this.lookTarget == null) { this.lookTarget = target.clone(); } //更新寻路target setRouteTarget(entity, this.target.clone()); //更新视线target setLookTarget(entity, this.lookTarget.clone()); var floor = target.floor(); if (oldTarget == null || !oldTarget.equals(floor)) entity.getBehaviorGroup().setForceUpdateRoute(true); oldTarget = floor; if (entity.distanceSquared(target) <= 3.5 && attackTick > coolDown) { Item item = entity instanceof EntityInventoryHolder holder ? holder.getItemInHand() : Item.fromString(MinecraftItemID.AIR.getNamespacedId()); float defaultDamage = 0; if (entity instanceof EntityCanAttack entityCanAttack) { defaultDamage = entityCanAttack.getDiffHandDamage(entity.getServer().getDifficulty()); } float itemDamage = item.getAttackDamage() + defaultDamage; Enchantment[] enchantments = item.getEnchantments(); if (item.applyEnchantments()) { for (Enchantment enchantment : enchantments) { itemDamage += enchantment.getDamageBonus(target); } } Map damage = new EnumMap<>(EntityDamageEvent.DamageModifier.class); damage.put(EntityDamageEvent.DamageModifier.BASE, itemDamage); float knockBack = 0.3f; if (item.applyEnchantments()) { Enchantment knockBackEnchantment = item.getEnchantment(Enchantment.ID_KNOCKBACK); if (knockBackEnchantment != null) { knockBack += knockBackEnchantment.getLevel() * 0.1f; } } EntityDamageByEntityEvent ev = new EntityDamageByEntityEvent(entity, target, EntityDamageEvent.DamageCause.ENTITY_ATTACK, damage, knockBack, item.applyEnchantments() ? enchantments : null); ev.setBreakShield(item.canBreakShield()); target.attack(ev); playAttackAnimation(entity); attackTick = 0; return target.getHealth() != 0; } //清空以待下次使用 this.lookTarget = null; this.target = null; return true; } @Override public void onStop(EntityIntelligent entity) { removeRouteTarget(entity); removeLookTarget(entity); //重置速度 entity.setMovementSpeed(0.1f); if (clearDataWhenLose) { entity.getBehaviorGroup().getMemoryStorage().clear(memory); } entity.setEnablePitch(false); this.target = null; this.lookTarget = null; } @Override public void onInterrupt(EntityIntelligent entity) { removeRouteTarget(entity); removeLookTarget(entity); //重置速度 entity.setMovementSpeed(0.1f); if (clearDataWhenLose) { entity.getBehaviorGroup().getMemoryStorage().clear(memory); } entity.setEnablePitch(false); this.target = null; this.lookTarget = null; } protected void playAttackAnimation(EntityIntelligent entity) { EntityEventPacket pk = new EntityEventPacket(); pk.eid = entity.getId(); pk.event = EntityEventPacket.ARM_SWING; Server.broadcastPacket(entity.getViewers().values(), pk); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy