Jump to content

Recommended Posts

Posted

I have a flying mob that basically moves like a ghast, I have a custom projectile, it is a AbstractArrow type not fireball, well my accuracy is not quite there yet, on some distances, it is perfectly accurate and on some distances inaccurate, this is my current attack goal:

 

    public static class RaybeamAttackGoal extends Goal
    {
        private final Celestroid mob;
        private final Celestroid rangedAttackMob;
        @Nullable
        private LivingEntity target;
        private int attackTime = -1;
        private int seeTime;
        private final int statecheck;
        private final double attackIntervalMin, attackIntervalMax, speedModifier;
        private final float attackRadius, attackRadiusSqr;

        public RaybeamAttackGoal(Celestroid celestroid, double speedIn, double dpsIn, float rangeIn, int state)
        {
            this(celestroid, speedIn, dpsIn, dpsIn, rangeIn, state);
        }

        public RaybeamAttackGoal(Celestroid gunswine, double speedIn, double atckIntervalMin, double atckIntervalMax, float atckRadius, int state)
        {

              this.rangedAttackMob =  gunswine;
              this.mob =  gunswine;
              this.speedModifier = speedIn;
              this.attackIntervalMin = atckIntervalMin;
              this.attackIntervalMax = atckIntervalMax;
              this.attackRadius = atckRadius;
              this.attackRadiusSqr = atckRadius * atckRadius;
              this.statecheck = state;
              this.setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK));
        }


        public boolean canUse()
        {
            LivingEntity livingentity = this.mob.getTarget();
            if (livingentity != null && livingentity.isAlive())
            {
                this.target = livingentity;
                return true;
            } else  { return false; }
        }

        public boolean canContinueToUse() { return this.canUse() || !this.mob.getNavigation().isDone(); }

        public void stop() {
            this.target = null;
            this.seeTime = 0;
            this.attackTime = -1;
        }

        public boolean requiresUpdateEveryTick() { return true; }

        public void tick()
        {
            double d0 = this.mob.distanceToSqr(this.target.getX(), this.target.getY(), this.target.getZ());
            boolean flag = this.mob.getSensing().hasLineOfSight(this.target);
            if (flag) {
                ++this.seeTime;
            } else {
                this.seeTime = 0;
            }

            if (!(d0 > (double)this.attackRadiusSqr) && this.seeTime >= 5) {
                this.mob.getNavigation().stop();
            } else {
                this.mob.getNavigation().moveTo(this.target, this.speedModifier);
            }

            this.mob.getLookControl().setLookAt(this.target, 30.0F, 30.0F);
            if (--this.attackTime == 0) {
                if (!flag) {
                    return;
                }

                float f = (float)Math.sqrt(d0) / this.attackRadius;
                float f1 = Mth.clamp(f, 0.1F, 1.0F);
                this.rangedAttackMob.performRangedAttack(this.target, f1);
                this.attackTime = Mth.floor(f * (float)(this.attackIntervalMax - this.attackIntervalMin) + (float)this.attackIntervalMin);
            } else if (this.attackTime < 0) {
                this.attackTime = Mth.floor(Mth.lerp(Math.sqrt(d0) / (double)this.attackRadius, (double)this.attackIntervalMin, (double)this.attackIntervalMax));
            }
        }
    }

    public void performRangedAttack(LivingEntity livingEntity, float p_32142_)
    {
        RaygunBeam beam = new RaygunBeam(this.level, this);
        double d0 = livingEntity.getX() - this.getX();
        double d1 = livingEntity.getY(-3.3333333333333333D) - beam.getY();
        double d2 = livingEntity.getZ() - this.getZ();
        double d3 = Math.sqrt(d0 * d0 + d2 * d2);
        beam.shoot(d0, d1 + d3 * (double)0.2F, d2, 1.6F,0f);
        this.playSound(SoundEventsSTLCON.RAYGUN_SHOOT.get(), 2.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F));

        this.level.addFreshEntity(beam);
    }

 

What can I do or refactor so that the accuracy is basically like a fireball of the ghast, I tried actually creating a similar way of how ghast is made, so I did create before another projectile for testing purposes, which used same functionality as a fireball, then the accuracy was perfect as I wanted but obviously the projectile wouldn't do damage to the player. Thank you so much in advance cheers

Posted
//From AbstractSkeleton.class
//shoot() method parameters (x,y,z,velocity,inaccuracy)
abstractarrow.shoot(d0, d1 + d3 * (double)0.2F, d2, 1.6F, (float)(14 - this.level.getDifficulty().getId() * 4));
  

as you see in the last parameter its adjusting the inaccuracy of the shoot from a hardcoded number subtracted by the current world difficulty * 4. Now if you set it to 0 and  it'll be accurate and increasing the velocity makes it deal more damage and is a factor in the trajectory of the arrow. I think what you are trying to compare are two different things, the arrow first of all has drop off which compared to a fireball does not drop off and keeps its velocity constant. I have pulled the code from the Vanilla Ghast and Fireball to show you what it does compared to the Arrow

 

This is the code the Ghast uses to shoot a fireball

if (this.chargeTime == 20) {
	double d1 = 4.0D;
    Vec3 vec3 = this.ghast.getViewVector(1.0F);
    double d2 = livingentity.getX() - (this.ghast.getX() + vec3.x * 4.0D);
    double d3 = livingentity.getY(0.5D) - (0.5D + this.ghast.getY(0.5D));
    double d4 = livingentity.getZ() - (this.ghast.getZ() + vec3.z * 4.0D);
    if (!this.ghast.isSilent()) {
    	level.levelEvent((Player)null, 1016, this.ghast.blockPosition(), 0);
    }

    LargeFireball largefireball = new LargeFireball(level, this.ghast, d2, d3, d4, this.ghast.getExplosionPower());
    largefireball.setPos(this.ghast.getX() + vec3.x * 4.0D, this.ghast.getY(0.5D) + 0.5D, largefireball.getZ() + vec3.z * 4.0D);
    level.addFreshEntity(largefireball);
	this.chargeTime = -40;
}

 

 

This is the AbstractHurtingProjectile.class code that calls when its spawned in the world

public void tick() {
      Entity entity = this.getOwner();
      if (this.level.isClientSide || (entity == null || !entity.isRemoved()) && this.level.hasChunkAt(this.blockPosition())) {
         super.tick();
         if (this.shouldBurn()) {
            this.setSecondsOnFire(1);
         }

         HitResult hitresult = ProjectileUtil.getHitResult(this, this::canHitEntity);
         if (hitresult.getType() != HitResult.Type.MISS && !net.minecraftforge.event.ForgeEventFactory.onProjectileImpact(this, hitresult)) {
            this.onHit(hitresult);
         }

         this.checkInsideBlocks();
         Vec3 vec3 = this.getDeltaMovement();
         double d0 = this.getX() + vec3.x;
         double d1 = this.getY() + vec3.y;
         double d2 = this.getZ() + vec3.z;
         ProjectileUtil.rotateTowardsMovement(this, 0.2F);
         float f = this.getInertia();
         if (this.isInWater()) {
            for(int i = 0; i < 4; ++i) {
               float f1 = 0.25F;
               this.level.addParticle(ParticleTypes.BUBBLE, d0 - vec3.x * 0.25D, d1 - vec3.y * 0.25D, d2 - vec3.z * 0.25D, vec3.x, vec3.y, vec3.z);
            }

            f = 0.8F;
         }

         this.setDeltaMovement(vec3.add(this.xPower, this.yPower, this.zPower).scale((double)f));
         this.level.addParticle(this.getTrailParticle(), d0, d1 + 0.5D, d2, 0.0D, 0.0D, 0.0D);
         this.setPos(d0, d1, d2);
      } else {
         this.discard();
      }
   }

 

AbstractArrow.class tick() method, the area in where it checks if a block was hit or not

if (this.inGround && !flag) {
         if (this.lastState != blockstate && this.shouldFall()) {
            this.startFalling();
         } else if (!this.level.isClientSide) {
            this.tickDespawn();
         }

         ++this.inGroundTime;
      }

ShouldFall check and StartFalling method

private boolean shouldFall() {
      return this.inGround && this.level.noCollision((new AABB(this.position(), this.position())).inflate(0.06D));
   }

   private void startFalling() {
      this.inGround = false;
      Vec3 vec3 = this.getDeltaMovement();
      this.setDeltaMovement(vec3.multiply((double)(this.random.nextFloat() * 0.2F), (double)(this.random.nextFloat() * 0.2F), (double)(this.random.nextFloat() * 0.2F)));
      this.life = 0;
   }

as you see the arrow is more complex in physics compared to the fireball, if you want it to be just as accurate as the fireball I think you would have to override a custom extended AbstractArrow or just outright make your own version of the AbstractArrow class

Posted

You also mentioned you made a similar projectile like the Ghast does what class did you derive it from AbstractHurtingProjectile or AbstractArrow? 

Posted
1 hour ago, sFXprt said:

You also mentioned you made a similar projectile like the Ghast does what class did you derive it from AbstractHurtingProjectile or AbstractArrow? 

 

 

Like you mentioned how I could make my own AbstractArrow, I actually went on creating my own AbstractHurtingProjectile since I think the previous one I made the testing purpose one was AbstractArrow if I recall. Everything is working as intended now so, thank you so much for your time appreciate it, and yes I had some issues regarding where it shoots, so I copied/used over ghast as you mentioned ♥

  • Like 1
Posted
On 5/7/2023 at 3:20 AM, Feroov said:

 

 

Like you mentioned how I could make my own AbstractArrow, I actually went on creating my own AbstractHurtingProjectile since I think the previous one I made the testing purpose one was AbstractArrow if I recall. Everything is working as intended now so, thank you so much for your time appreciate it, and yes I had some issues regarding where it shoots, so I copied/used over ghast as you mentioned ♥

Nice glad to see you got it working man!

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • When I first heard about Bitcoin back in 2018, I was skeptical. The idea of a decentralized, digital currency seemed too good to be true. But I was intrigued as I learned more about the technology behind it and its potential. I started small, investing just a few hundred dollars, dipping my toes into the cryptocurrency waters. At first, it was exhilarating to watch the value of my investment grow exponentially. I felt like I was part of the future, an early adopter of this revolutionary new asset. But that euphoria was short-lived. One day, I logged into my digital wallet only to find it empty - my Bitcoin had vanished without a trace. It turned out that the online exchange I had trusted had been hacked, and my funds were stolen. I was devastated, both financially and emotionally. All the potential I had seen in Bitcoin was tainted by the harsh reality that with decentralization came a lack of regulation and oversight. My hard-earned money was gone, lost to the ether of the digital world. This experience taught me a painful lesson about the price of trust in the uncharted territory of cryptocurrency. While the technology holds incredible promise, the risks can be catastrophic if you don't approach it with extreme caution. My Bitcoin investment gamble had failed, and I was left to pick up the pieces, wiser but poorer for having placed my faith in the wrong hands. My sincere appreciation goes to MUYERN TRUST HACKER. You are my hero in recovering my lost funds. Send a direct m a i l ( muyerntrusted ( @ ) mail-me ( . )c o m ) or message on whats app : + 1 ( 4-4-0 ) ( 3 -3 -5 ) ( 0-2-0-5 )
    • You could try posting a log (if there is no log at all, it may be the launcher you are using, the FAQ may have info on how to enable the log) as described in the FAQ, however this will probably need to be reported to/remedied by the mod author.
    • So me and a couple of friends are playing with a shitpost mod pack and one of the mods in the pack is corail tombstone and for some reason there is a problem with it, where on death to fire the player will get kicked out of the server and the tombstone will not spawn basically deleting an entire inventory, it doesn't matter what type of fire it is, whether it's from vanilla fire/lava, or from modded fire like ice&fire/lycanites and it's common enough to where everyone on the server has experienced at least once or twice and it doesn't give any crash log. a solution to this would be much appreciated thank you!
    • It is 1.12.2 - I have no idea if there is a 1.12 pack
  • Topics

×
×
  • Create New...

Important Information

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