Jump to content

[1.10.2] Ray trace for gun shot does not find any entities


Recommended Posts

Posted

For the guns in my mod I am using ray tracing (kinda like hit scan) to check for a hit. For that purpose I have created a helper method that is fired on the server when a certain item is leftclicked. In a custom method in my ItemBase class that is confirmed to work I am calling this ray trace method:

ArrayList<HitData> hits = RayTraceUtils.rayTraceEntities(world, player, Utils.getPlayerPosition(player), player.getLookVec().normalize(), ConfigHandler.maxRange, 1);

The HitData object is just a wrapper around a RayTraceResult with additional data.

This is what this method then does:

public static ArrayList<HitData> rayTraceEntities(World world, EntityPlayer shooter, Position startPos, Vec3d dirVecNormal, int length, int maxHitCount)
{
    Vec3d startVec = new Vec3d(startPos.getX(), startPos.getY(), startPos.getZ());
    Vec3d endVec   = startVec.add(dirVecNormal.scale(length)).normalize();

    RayTraceResult result = world.rayTraceBlocks(startVec, endVec, false, true, false);

    Vec3d aabbVec1 = startVec.add(new Vec3d(0, -1, 0));
    Vec3d aabbVec2 = endVec.add(new Vec3d(0, 1, 0));

    AxisAlignedBB bb = new AxisAlignedBB(aabbVec1, result != null ? result.hitVec.add(new Vec3d(0, 1, 0)) : aabbVec2);
    List<Entity> entities = world.getEntitiesInAABBexcluding(shooter, bb, entityPredicate);

    ArrayList<HitData> entitiesInVector = new ArrayList<>();
    Vec3d startVecEntityCheck = startVec.normalize();
    Vec3d endVecEntityCheck = result != null ? result.hitVec.normalize() : endVec.normalize();

    for (Entity entity : entities)
    {
        EntityLivingBase victim = (EntityLivingBase)entity;
        if (!victim.noClip && victim.getCollisionBoundingBox() != null)
        {
            RayTraceResult intercept = victim.getCollisionBoundingBox().calculateIntercept(startVecEntityCheck, endVecEntityCheck);
            if (intercept != null)
            {
                intercept.hitInfo = isHeadshot(intercept.hitVec, intercept.entityHit);
                entitiesInVector.add(new HitData(victim, intercept, shooter));
                if (entitiesInVector.size() >= maxHitCount) { break; }
            }
        }
    }

    return entitiesInVector;
}

The Position object is kinda like BlockPos but with doubles instead of ints. For some reason this method always returns an empty list.

Posted (edited)
38 minutes ago, XFactHD said:

The Position object is kinda like BlockPos but with doubles instead of ints.

So a copy of Vec3d class?

 

startVec.add(dirVecNormal.scale(length)).normalize();

World::rayTraceBlocks takes a start vector and an end vector, not a start vector and a ray. By normalizing this vector you are essentially raycasting from startVec to around 0,0,0

38 minutes ago, XFactHD said:

entityPredicate

I assume this is a static predicate somewhere in this class? It would be nice to see this aswell.

 

38 minutes ago, XFactHD said:

Vec3d startVecEntityCheck = startVec.normalize();

Vec3d endVecEntityCheck = result != null ? result.hitVec.normalize() : endVec.normalize();

Again - normalizing a vector turns it into a [-1 - 1] vector. AxisAlignedBB's calculateIntercept method will pretty much always return null as long as the BB is not at 0,0,0(and it isn't as long as the entity itself is not at 0,0,0) because it compares the coordinates of the vector with it's coordinates.

You can see how vanilla raytraces entities at EntityRenderer::getMouseOver or for a cleaner code example at EntityArrow::findEntityOnPath

Edited by V0idWa1k3r
Posted

This is the entity predicate:

private static final Predicate<? super Entity> entityPredicate = Predicates.and(EntitySelectors.NOT_SPECTATING, new Predicate<Entity>()
{
    public boolean apply(@Nullable Entity entity) { return entity != null && entity.canBeCollidedWith() && entity instanceof EntityLivingBase; }
});

 

This is what I changed based on your comment on normalizing a vector (changes marked):

public static ArrayList<HitData> rayTraceEntities(World world, EntityPlayer shooter, Position startPos, Vec3d dirVecNormal, int length, int maxHitCount)
{
    Vec3d startVec = new Vec3d(startPos.getX(), startPos.getY(), startPos.getZ());
    Vec3d endVec   = startVec.add(dirVecNormal.scale(length)); <--

    RayTraceResult result = world.rayTraceBlocks(startVec, endVec, false, true, false);

    Vec3d aabbVec1 = startVec.add(new Vec3d(0, -1, 0));
    Vec3d aabbVec2 = endVec.add(new Vec3d(0, 1, 0));

    AxisAlignedBB bb = new AxisAlignedBB(aabbVec1, result != null ? result.hitVec.add(new Vec3d(0, 1, 0)) : aabbVec2);
    List<Entity> entities = world.getEntitiesInAABBexcluding(shooter, bb, entityPredicate);

    ArrayList<HitData> entitiesInVector = new ArrayList<>();
    Vec3d startVecEntityCheck = startVec; <--
    Vec3d endVecEntityCheck = result != null ? result.hitVec : endVec; <--

    for (Entity entity : entities)
    {
        EntityLivingBase victim = (EntityLivingBase)entity;
        if (!victim.noClip && victim.getCollisionBoundingBox() != null)
        {
            RayTraceResult intercept = victim.getCollisionBoundingBox().calculateIntercept(startVecEntityCheck, endVecEntityCheck);
            if (intercept != null)
            {
                intercept.hitInfo = isHeadshot(intercept.hitVec, intercept.entityHit);
                entitiesInVector.add(new HitData(victim, intercept, shooter));
                if (entitiesInVector.size() >= maxHitCount) { break; }
            }
        }
    }

    return entitiesInVector;
}

but this doesn't work either.

Posted

Entity::getCollisionBoundingBox appears to return null in most cases, so this check

9 minutes ago, XFactHD said:

if (!victim.noClip && victim.getCollisionBoundingBox() != null)

will always fail. Use Entity::getEntityBoundingBox instead.

Posted

That is strange. I used your code, corrected the following and it worked for the most part. Something must be wrong with something else then.

Could you please show the Utils::getPlayerPosition method? Make sure that you are adding the result of Entity::getEyeHeight to the Y coordinate

Posted

This is the getPlayerPosition method:

public static Position getPlayerPosition(EntityPlayer player)
{
    return new Position(player.posX, player.posY, player.posZ);
}

I changed this:

Vec3d startVec = new Vec3d(startPos.getX(), startPos.getY(), startPos.getZ());

to this:

Vec3d startVec = new Vec3d(startPos.getX(), startPos.getY() + shooter.getEyeHeight(), startPos.getZ());

as per your comment but it still doesn't work.

This is the full method right now:

public static ArrayList<HitData> rayTraceEntities(World world, EntityPlayer shooter, Position startPos, Vec3d dirVecNormal, int length, int maxHitCount)
{
    Vec3d startVec = new Vec3d(startPos.getX(), startPos.getY() + shooter.getEyeHeight(), startPos.getZ());
    Vec3d endVec   = startVec.add(dirVecNormal.scale(length));

    RayTraceResult result = world.rayTraceBlocks(startVec, endVec, false, true, false);

    Vec3d aabbVec1 = startVec.add(new Vec3d(0, -1, 0));
    Vec3d aabbVec2 = endVec.add(new Vec3d(0, 1, 0));

    AxisAlignedBB bb = new AxisAlignedBB(aabbVec1, result != null ? result.hitVec.add(new Vec3d(0, 1, 0)) : aabbVec2);
    List<Entity> entities = world.getEntitiesInAABBexcluding(shooter, bb, entityPredicate);

    ArrayList<HitData> entitiesInVector = new ArrayList<>();
    Vec3d endVecEntityCheck = result != null ? result.hitVec : endVec;

    for (Entity entity : entities)
    {
        EntityLivingBase victim = (EntityLivingBase)entity;
        if (!victim.noClip && victim.getEntityBoundingBox() != null)
        {
            RayTraceResult intercept = victim.getEntityBoundingBox().calculateIntercept(startVec, endVecEntityCheck);
            if (intercept != null)
            {
                intercept.hitInfo = isHeadshot(intercept.hitVec, intercept.entityHit);
                entitiesInVector.add(new HitData(victim, intercept, shooter));
                if (entitiesInVector.size() >= maxHitCount) { break; }
            }
        }
    }

    return entitiesInVector;
}
Posted

Well, I'm not really sure why is it not working for you. I can suggest removing the adition of the [0, 1, 0] vector here as it only offsets the actual calculations

15 minutes ago, XFactHD said:

result.hitVec.add(new Vec3d(0, 1, 0))

 

Could you please setup a github repository of your mod so I can debug it with a bit more than just this portion of the code you are giving? Because it works for me, that must mean that there is an issue somewhere else.

Posted (edited)

With the statement you quoted I am making sure that the AxisAlignedBoundingBox used for getEntittiesInAABB has a height of atleast one because an AABB with a height of zero can't intersect with anything.

I will create a GitHub repository and edit this post with the link.

EDIT: Here is the GitHub link: https://github.com/XFactHD/RainbowSixSiegeMC

Edited by XFactHD
Posted (edited)

Your RayTraceUtils::isHeadshot method is broken. If the entity passed is null it throws a NullPointerException that gets logged but due to the way the game processes the left click action it doesn't crash the game. And it is null because AxisAlignedBB::calculateIntercept has zero clues about any entities and thus is unable to pass one into the RayTraceResult's entityHit field value. You can safely pass the current entity being iterated into the method instead. 

 

As a side note: ItemMagazine::getSubItems is broken. As soon as you open the "search items" creative tab the game crashes because subItems contains all the items in the current tab, and for the search items tab it contains, well, all items added to tabs in the game. For some of them ItemStack::getMetadata will return a value greater than the size of your EnumMagazine enum.

Edited by V0idWa1k3r
Posted

I fixed it by setting the RayTraceResult's entityHit value to the entity currently being worked on as I need that value later on. Now it is working. Thank you very much for your great support.

 

Also, on your side note: this general error applys to many of the items in this mod.

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.