Моб нападает на сородичей - как исправить?

Версия Minecraft
1.16.5
198
1
24
Пытаюсь сделать зомби-волка. Нападать он должен, в т.ч., на нормальных волков. Но, конечно же, не на других зомби-волков. А он это делает! Я так понимаю, это из-за того, я расширил класс ванильного волка, заменив ИИ?

Вот его код:
ZombieWolf.java:
public class ZombieWolf extends WolfEntity {

    public ZombieWolf(EntityType<? extends ZombieWolf> zombie, World world) {
        super(zombie, world);
    }

    public static AttributeModifierMap.MutableAttribute createAttributes() {
        return MobEntity.createMobAttributes().add(Attributes.MOVEMENT_SPEED, (double)0.3F).add(Attributes.MAX_HEALTH, 20.0D).add(Attributes.ATTACK_DAMAGE, 2.0D);
    }

    @Override
    protected void registerGoals() {
        this.goalSelector.addGoal(1, new SwimGoal(this));
        this.goalSelector.addGoal(2, new SitGoal(this));
        this.goalSelector.addGoal(4, new LeapAtTargetGoal(this, 0.4F));
        this.goalSelector.addGoal(5, new MeleeAttackGoal(this, 1.0D, true));
        this.goalSelector.addGoal(8, new WaterAvoidingRandomWalkingGoal(this, 1.0D));
        this.goalSelector.addGoal(10, new LookAtGoal(this, PlayerEntity.class, 8.0F));
        this.goalSelector.addGoal(10, new LookRandomlyGoal(this));
        this.targetSelector.addGoal(3, (new HurtByTargetGoal(this)).setAlertOthers());
        this.targetSelector.addGoal(7, new NearestAttackableTargetGoal<>(this, PlayerEntity.class, false));
        this.targetSelector.addGoal(7, new NearestAttackableTargetGoal<>(this, WolfEntity.class, false));
        this.targetSelector.addGoal(7, new NearestAttackableTargetGoal<>(this, VillagerEntity.class, false));
        this.targetSelector.addGoal(7, new NearestAttackableTargetGoal<>(this, IronGolemEntity.class, false));
        this.targetSelector.addGoal(7, new NearestAttackableTargetGoal<>(this, SheepEntity.class, false));
        this.targetSelector.addGoal(7, new NearestAttackableTargetGoal<>(this, RabbitEntity.class, false));
        this.targetSelector.addGoal(7, new NearestAttackableTargetGoal<>(this, TurtleEntity.class, false));
        this.targetSelector.addGoal(7, new NearestAttackableTargetGoal<>(this, CatEntity.class, false));
    }

    protected SoundEvent getAmbientSound() {
        return SoundEvents.WOLF_HOWL;
    }
    protected SoundEvent getHurtSound(DamageSource p_184601_1_) {
        return SoundEvents.WOLF_GROWL;
    }
    protected SoundEvent getDeathSound() {
        return SoundEvents.WOLF_DEATH;
    }
    protected SoundEvent getStepSound() {
        return SoundEvents.WOLF_STEP;
    }
    protected void playStepSound(BlockPos p_180429_1_, BlockState p_180429_2_) {
        this.playSound(this.getStepSound(), 0.15F, 1.0F);
    }

    public boolean checkSpawnRules(IServerWorld world, SpawnReason reason) {
       return super.checkSpawnRules(world, reason);
    }
}
Есть ли простой способ избавиться от этого (т.е. оставив родительский класс как есть, чтобы использовать рендер ванильного волка)?
 
Решение
Неужели так тяжело открыть AI таску, пройтись по вызовам и найти логику кода?
Да, там не сравнивается напрямую класс, а проверяется наследует ли указанный класс.
Создай свой таск и напиши как душе угодно.

tox1cozZ

aka Agravaine
8,456
598
2,893
Неужели так тяжело открыть AI таску, пройтись по вызовам и найти логику кода?
Да, там не сравнивается напрямую класс, а проверяется наследует ли указанный класс.
Создай свой таск и напиши как душе угодно.
 
198
1
24
Пробовал. Не совсем написать свой, а слегка изменить ванильный NearestAttackableTargetGoal. Есть там такой код:

Ванильный код::
public void setTarget(@Nullable LivingEntity p_234054_1_) {
      this.target = p_234054_1_;
   }

Заменил его на такой:

Дополненый код::
public void setTarget(@Nullable LivingEntity p_234054_1_) {
      if (p_234054_1_.getClass() != this.mob.getClass()) {
         this.target = p_234054_1_;
      } else {
         this.target = null;
      }
   }

Перекомпилировал, перезапустил - а они всё равно между собой дерутся...
 
198
1
24
Поковыряв код ещё немного, обнаружил, что нужно изменить не setTarget() а canUse(), и они перестали жрать друг друга. По крайней мере сразу... Теперь съедают того, кто напал на ванильного волка. Получается странная ситуация, когда они, с одной стороны, враждебны к ванильным волкам, но с другой сами себя такими считают и нападать на ванильного волка нужно, но нельзя... Видимо, надо переделать также HurtByTargetGoal.
 
198
1
24
Проблема в том, что нападают они не потому, что видят, как волка обижают, а потому, что он зовёт на помощь, не видя разницы между ними и волками. А как переделать ванильного волка я понятия не имею...
 
198
1
24
В общем, решил эту проблему, написав AI таску NeverAttackTargetGoal, запрещающую атаковать указанную сущность:
AI таска "Никогда не атаковать ...":
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.MobEntity;
import net.minecraft.entity.ai.goal.Goal;

public class NeverAttackTargetGoal <T extends LivingEntity> extends Goal {
    protected final MobEntity mob;
    protected final Class<T> neverAttackThis;
    public NeverAttackTargetGoal(MobEntity mob, Class<T> neverAttackThis){
        this.mob = mob;
        this.neverAttackThis = neverAttackThis;
    }

    @Override
    public boolean canUse() {
        if(this.mob.getTarget() == null) {
            return false;
        }else if(this.mob.getTarget().getClass() != this.neverAttackThis){
            return false;
        } else return true;
    }

    public boolean canContinueToUse() {
        LivingEntity livingentity = this.mob.getTarget();
        if (livingentity == null) {
            return false;
        } else return true;
    }

    public void start() {
        if(this.mob.getTarget() != null && this.mob.getTarget().getClass() == this.neverAttackThis) {
            this.mob.setTarget((LivingEntity)null);
        }
    }

    public void stop() {
    }
}
 
198
1
24
Неужели так тяжело открыть AI таску, пройтись по вызовам и найти логику кода?
Да, там не сравнивается напрямую класс, а проверяется наследует ли указанный класс.
Создай свой таск и напиши как душе угодно.
И всё-таки, я бы наверное долго тупил прежде чем это придумать, так что помечу ответ как решение :D
 
Сверху