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
  On 5/7/2023 at 8:31 AM, sFXprt said:

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

Expand  

 

 

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 10: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 ♥

Expand  

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

    • Recovering stolen Bitcoin can feel like an insurmountable challenge, especially after falling victim to scams that promise high returns with little investment. My journey began with excitement when I first learned about Bitcoin mining pools. The idea of earning substantial profits from a modest investment was enticing. I was encouraged to invest $5,200, and soon found myself caught in a web of endless demands for more money to access my funds. As time went on, I paid out hundreds of thousands of dollars, believing that each payment would finally unlock my investments. However, the requests never ceased, and I soon realized I was trapped in a scam. The weight of losing $826,000 worth of Bitcoin was unbearable, and I felt utterly helpless. I reached out to authorities, but their responses were disheartening, leaving me feeling even more isolated in my struggle. In my desperation, I even went to pray, seeking guidance and hope in what felt like a hopeless situation. I poured my heart out, asking for a sign or a way to recover my lost funds. It was during this time of reflection that I began searching for solutions online, hoping to find a way to recover my investments. That’s when I stumbled upon RAPID DIGITAL RECOVERY. At first, I was cynical after all, I had already been deceived so many times. However, I decided to reach out and share my story. The team at RAPID DIGITAL RECOVERY was understanding and compassionate, assuring me they had the expertise to help me recover my stolen Bitcoin. Within hours of providing them with the necessary information, I began to see progress. They guided me through the recovery process, keeping me informed every step of the way. It was surreal to watch as they worked diligently to trace my funds and navigate the complexities of the blockchain. To my astonishment, I received confirmation that my Bitcoin had been successfully recovered. The relief and joy I felt were indescribable. I had almost given up hope, but RAPID DIGITAL RECOVERY proved to be the lifeline I desperately needed. If you find yourself in a similar situation, I urge you to seek help from Reputable team at RAPID DIGITAL RECOVERY.  
    • https://mclo.gs/9Byd16j Hi, I've had my BetterMC world for a couple days now (1.19.2 vers & Fabric loader) but recently whenever I try to open the profile the minecraft launcher crashes and provides this error code. I've checked both this forum and google and haven't found any similar problems or solution to my problem. I'm not the best at reading crash logs but I gathered that there's an issue with fabric possibly, so I re-downloaded the same one on the modpack, then the latest version for 1.19.2 fabric and the issue still occurred. What can I do now?
    • it works now but idk why lmao. i removed terrablender and it didnt work. i then left it for a couple of days and, when i came back, updated the mods that needed updating because "what's the worst that could happen". i then tried launching it and now it works. i genuenly have no clue what i did to make it work, othen than updating the mods. so, thanks for your help
    • Add the crash-report or latest.log (logs-folder) with sites like https://mclo.gs/ and paste the link to it here  
  • Topics

  • Who's Online (See full list)

×
×
  • Create New...

Important Information

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