Jump to content

[1.15.1] How could I create a "catch projectile" type of behavior on a player?


Recommended Posts

Posted

How could I make behavior on the player that when the player sees the projectile "catches it" e.g a skeleton shoots the player but if the player is facing the arrow the player catches the projectile so far the event I think it has to do something with it is ProjectileImpactEvent, however, I'm not entirely sure how could I write that behavior. Here's my code

 

@SubscribeEvent
public static void onProjectileCatchEvent(ProjectileImpactEvent event) {

    if (event.getEntity() instanceof ArrowEntity) {
     event.setCanceled(true);
    }
}

 

Posted

From AbstractArrowEntity::tick

EntityRayTraceResult entityraytraceresult = this.rayTraceEntities(vec3d2, vec3d3);
if (entityraytraceresult != null) {
   raytraceresult = entityraytraceresult;
}

if (raytraceresult != null && raytraceresult.getType() == RayTraceResult.Type.ENTITY) {
   Entity entity = ((EntityRayTraceResult)raytraceresult).getEntity();
   Entity entity1 = this.getShooter();
   if (entity instanceof PlayerEntity && entity1 instanceof PlayerEntity && !((PlayerEntity)entity1).canAttackPlayer((PlayerEntity)entity)) {
      raytraceresult = null;
      entityraytraceresult = null;
   }
}

if (raytraceresult != null && raytraceresult.getType() != RayTraceResult.Type.MISS && !flag && !net.minecraftforge.event.ForgeEventFactory.onProjectileImpact(this, raytraceresult)) {
   this.onHit(raytraceresult);
   this.isAirBorne = true;
}

The event is fired in that fourth if statement. You should be able to get the Enity the arrow hit (if any) from the EntityRayTraceResult. Then I suppose you'll want to find out if the Entity is a player and if they were facing the appropriate direction at the time.

  • Thanks 1
Posted
8 hours ago, MoxLotus said:

From AbstractArrowEntity::tick


EntityRayTraceResult entityraytraceresult = this.rayTraceEntities(vec3d2, vec3d3);
if (entityraytraceresult != null) {
   raytraceresult = entityraytraceresult;
}

if (raytraceresult != null && raytraceresult.getType() == RayTraceResult.Type.ENTITY) {
   Entity entity = ((EntityRayTraceResult)raytraceresult).getEntity();
   Entity entity1 = this.getShooter();
   if (entity instanceof PlayerEntity && entity1 instanceof PlayerEntity && !((PlayerEntity)entity1).canAttackPlayer((PlayerEntity)entity)) {
      raytraceresult = null;
      entityraytraceresult = null;
   }
}

if (raytraceresult != null && raytraceresult.getType() != RayTraceResult.Type.MISS && !flag && !net.minecraftforge.event.ForgeEventFactory.onProjectileImpact(this, raytraceresult)) {
   this.onHit(raytraceresult);
   this.isAirBorne = true;
}

The event is fired in that fourth if statement. You should be able to get the Enity the arrow hit (if any) from the EntityRayTraceResult. Then I suppose you'll want to find out if the Entity is a player and if they were facing the appropriate direction at the time.

Hi, thanks for the tip, tried to implement it to my code but I just can't seem to get it to work, tried to do it without the condition of the player looking at it for testing purposes and I just couldn't make it work, do you have any idea why? Here's my code: 

@SubscribeEvent
public static void onProjectileHitEvent(ProjectileImpactEvent event) {


        EntityRayTraceResult entityRayTraceResult = new EntityRayTraceResult(event.getEntity(), event.getRayTraceResult().getHitVec());

        Entity entity = entityRayTraceResult.getEntity();

        if (entity instanceof PlayerEntity) {

            PlayerEntity playerEntity = (PlayerEntity) entity;
            if (playerEntity.getItemStackFromSlot(EquipmentSlotType.CHEST).getItem() == ItemHolder.BATMAN_CHEST) {
                event.setCanceled(true);
            }

        }
    }
Posted

Instead of creating a new RayTraceResult you should have an instanceof test and cast event.getRayTraceResult.

 

As for your question, does it do what you expect if you always cancel the event?

  • Thanks 1
Posted
10 hours ago, MoxLotus said:

Instead of creating a new RayTraceResult you should have an instanceof test and cast event.getRayTraceResult.

 

As for your question, does it do what you expect if you always cancel the event?

Got it, thanks! no, it was just for testing purposes now I got to figure out the "catch" also I noticed that with this code if I get hit by 2 arrows consecutively it crashes:

@SubscribeEvent
public static void onProjectileHitEvent(ProjectileImpactEvent event) {


        if (event.getRayTraceResult() instanceof EntityRayTraceResult) {
            EntityRayTraceResult entityRayTraceResult = (EntityRayTraceResult) event.getRayTraceResult();

            if (entityRayTraceResult.getEntity() instanceof PlayerEntity) {

                PlayerEntity playerEntity = (PlayerEntity) entityRayTraceResult.getEntity();
                if (playerEntity.getItemStackFromSlot(EquipmentSlotType.CHEST).getItem() == ItemHolder.BATMAN_CHEST) {

                    event.setCanceled(true);

                }

                 }
            }
        }
Posted

Any helpful crash logs? I can't give much insight without those.

It's not convenient for me to dig through code right now, but somewhere in Entity or EntityLiving there should be functions that deal with which direction the entity is looking in. Maybe try finding examples in the Enderman code, since line of sight is so important to them. If you can find it, figuring out if the ray-trace from the arrow came from the appropriate direction should just be a question of math.

Do my sense of aesthetic a favor and combine those first two if statements with a &&. That way you cast your two variables only if you actually need them.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.