2424import net .minecraft .server .level .ServerPlayer ;
2525import net .minecraft .util .Mth ;
2626import net .minecraft .world .InteractionHand ;
27- import net .minecraft .world .damagesource .DamageSource ;
2827import net .minecraft .world .entity .Entity ;
2928import net .minecraft .world .entity .EquipmentSlot ;
3029import net .minecraft .world .entity .HumanoidArm ;
5756
5857public class ImpalerItem extends LivingGunItem implements ItemTooltipStyleProvider , GeoItem {
5958
59+ public static final float CHARGE_DURATION = 1.79f + 0.17f ; //based on animation length of "charging_shot" + "holding_shot"
60+
6061 protected static final UUID BASE_MOVEMENT_SPEED_UUID = UUID .fromString ("efc325ad-c747-4c0e-80c2-f3f0f4261e91" );
6162
6263 private final AnimatableInstanceCache cache = GeckoLibUtil .createInstanceCache (this );
@@ -66,15 +67,15 @@ public class ImpalerItem extends LivingGunItem implements ItemTooltipStyleProvid
6667 public ImpalerItem (int maxNutrients , Properties properties ) {
6768 super (maxNutrients , properties ,
6869 GunProperties .builder ()
69- .shootBehavior (GunProperties .ShootBehavior .ON_FULL_CHARGE )
70- .timeBetweenShots (2 * 20 )
71- .maxAmmo (1 ).reloadDuration (10 * 20 ).autoReload ()
70+ .shootBehavior (GunProperties .ShootBehavior .ON_RELEASE_INSTANT )
71+ .timeBetweenShots (Mth . ceil ( CHARGE_DURATION * 20f ) )
72+ .maxAmmo (1 ).reloadDuration (3 * 20 ).autoReload ()
7273 .build (),
7374 ModProjectiles .IMPALER_PROJECTILE );
7475
7576 ImmutableMultimap .Builder <Attribute , AttributeModifier > builder = ImmutableMultimap .builder ();
7677 builder .put (Attributes .ATTACK_SPEED , new AttributeModifier (BASE_ATTACK_SPEED_UUID , "Weapon modifier" , -3.5f , AttributeModifier .Operation .ADDITION ));
77- builder .put (Attributes .MOVEMENT_SPEED , new AttributeModifier (BASE_MOVEMENT_SPEED_UUID , "Weapon modifier" , -0.25f , AttributeModifier .Operation .MULTIPLY_BASE ));
78+ builder .put (Attributes .MOVEMENT_SPEED , new AttributeModifier (BASE_MOVEMENT_SPEED_UUID , "Weapon modifier" , -0.125f , AttributeModifier .Operation .MULTIPLY_BASE ));
7879 defaultModifiers = builder .build ();
7980
8081 GeoItem .registerSyncedAnimatable (this );
@@ -126,8 +127,12 @@ public float modifyProjectileDamage(float baseDamage, ItemStack stack) {
126127
127128 @ Override
128129 public void shoot (ServerLevel level , LivingEntity shooter , InteractionHand usedHand , ItemStack projectileWeapon ) {
130+ float elapsedDuration = (float ) projectileWeapon .getUseDuration () - ((float ) shooter .getUseItemRemainingTicks ());
131+ float maxChargeDuration = getDelayBetweenShots (projectileWeapon );
132+ float chargePercentage = Mth .clamp (elapsedDuration / maxChargeDuration , 0.1f , 1f );
133+
129134 boolean success = configuredProjectile .shoot (level , shooter ,
130- baseVelocity -> modifyProjectileVelocity (baseVelocity , projectileWeapon ),
135+ baseVelocity -> modifyProjectileVelocity (baseVelocity * chargePercentage , projectileWeapon ),
131136 baseDamage -> modifyProjectileDamage (baseDamage , projectileWeapon ),
132137 baseKnockBack -> modifyProjectileKnockBack (baseKnockBack , projectileWeapon ),
133138 baseInaccuracy -> modifyProjectileInaccuracy (baseInaccuracy , projectileWeapon ),
@@ -149,14 +154,15 @@ public void shoot(ServerLevel level, LivingEntity shooter, InteractionHand usedH
149154 boolean isAnchored = shooter .onGround () && shooter .isCrouching ();
150155 double reduction = isAnchored ? 0.25d : 0.5d ;
151156
152- float velocity = configuredProjectile .velocity (); //TODO: get final velocity e.g. velocity * chargePercentage
157+ float velocity = modifyProjectileVelocity ( configuredProjectile .velocity () * chargePercentage , projectileWeapon );
153158
154159 Vec3 recoil = shooter .getLookAngle ().normalize ().scale (-1d ).scale (velocity * reduction );
155160 shooter .push (recoil .x , recoil .y , recoil .z ); //sets hasImpulse to true
156161 shooter .fallDistance = 0f ;
157162
158- DamageSource damageSource = level .damageSources ().explosion (shooter , shooter );
159- shooter .hurt (damageSource , velocity * 0.5f );
163+ // "self" damage
164+ //DamageSource damageSource = level.damageSources().explosion(shooter, shooter);
165+ //shooter.hurt(damageSource, velocity * 0.5f);
160166
161167 if (!shooter .hurtMarked && shooter instanceof ServerPlayer serverPlayer ) {
162168 // Important:
@@ -212,7 +218,7 @@ private static boolean isHandPartOfArm(LocalPlayer player, HumanoidArm arm, Inte
212218 private static void applyArmTransform (PoseStack poseStack , HumanoidArm arm , float progress , float ticks ) {
213219 float direction = arm == HumanoidArm .RIGHT ? 1f : -1f ;
214220 float invProgress = 1f - progress ;
215- // float yOffset = 0.1f * -0.6f;
221+ //float yOffset = 0.1f * -0.6f;
216222 poseStack .mulPose (Axis .YP .rotationDegrees (10f * invProgress + direction * Mth .cos (ticks * 0.09f ) * 1f ));
217223 poseStack .mulPose (Axis .XP .rotationDegrees (-15f * invProgress + direction * Mth .sin (ticks * 0.067f ) * 1f ));
218224 poseStack .translate (0.56f * direction , -0.52f , -0.72f ); //align item to "item holding position of hand" on screen
@@ -236,7 +242,8 @@ public HumanoidModel.ArmPose getArmPose(LivingEntity entityLiving, InteractionHa
236242 public boolean applyForgeHandTransform (PoseStack poseStack , LocalPlayer player , HumanoidArm arm , ItemStack itemInHand , float partialTick , float equipProcess , float swingProcess ) {
237243 if (player .isUsingItem () && player .getUseItemRemainingTicks () > 0 && isHandPartOfArm (player , arm , player .getUsedItemHand ())) {
238244 float elapsedDuration = (float ) itemInHand .getUseDuration () - ((float ) player .getUseItemRemainingTicks () - partialTick + 1f );
239- float aimProgress = elapsedDuration / 2.5f ;
245+ float maxChargeDuration = getDelayBetweenShots (itemInHand );
246+ float aimProgress = elapsedDuration / maxChargeDuration ;
240247 if (aimProgress > 1f ) {
241248 aimProgress = 1f ;
242249 }
@@ -275,9 +282,8 @@ protected static final class Animations {
275282 private static final List <TriggerableAnimation > TRIGGERABLE_ANIMATIONS = new ArrayList <>();
276283
277284 static final TriggerableAnimation SHOOT = register (MAIN_CONTROLLER , "shoot" , RawAnimation .begin ().thenPlay ("barrel_recoil" ));
278- static final RawAnimation CHARGE_UP_SHOT = RawAnimation .begin ().thenPlay ("charging_shot" );
279- static final RawAnimation NO_PROJECTILE = RawAnimation .begin ().thenPlay ("no_projectile" );
280- static final RawAnimation GROW_PROJECTILE = RawAnimation .begin ().thenPlay ("grow_projectile" );
285+ static final RawAnimation CHARGE_UP_SHOT = RawAnimation .begin ().thenPlay ("charging_shot" ).thenPlay ("holding_shot" );
286+ static final RawAnimation DEFAULT_STATE = RawAnimation .begin ().thenPlay ("default_state" );
281287
282288 private Animations () {}
283289
@@ -286,30 +292,15 @@ static void registerControllers(ImpalerItem animatable, AnimatableManager.Contro
286292 registerTriggerableAnimations (mainController );
287293 controllers .add (mainController );
288294
289- controllers .add (new AnimationController <>(animatable , "charge_up " , state -> {
295+ controllers .add (new AnimationController <>(animatable , "charging " , state -> {
290296 ImpalerItem impalerItem = state .getAnimatable ();
291297 ItemStack stack = state .getData (DataTickets .ITEMSTACK );
292298
293299 if (impalerItem .getGunState (stack ) == GunState .SHOOTING_OR_CHARGING ) {
294300 return state .setAndContinue (CHARGE_UP_SHOT );
295301 }
296302
297- return PlayState .STOP ;
298- }));
299-
300- controllers .add (new AnimationController <>(animatable , "projectile" , state -> {
301- ImpalerItem impalerItem = state .getAnimatable ();
302- ItemStack stack = state .getData (DataTickets .ITEMSTACK );
303-
304- if (impalerItem .getGunState (stack ) == GunState .RELOADING ) {
305- return state .setAndContinue (GROW_PROJECTILE );
306- }
307-
308- if (!impalerItem .hasAmmo (stack )) {
309- return state .setAndContinue (NO_PROJECTILE );
310- }
311-
312- return PlayState .STOP ; //show projectile
303+ return state .setAndContinue (DEFAULT_STATE );
313304 }));
314305 }
315306
0 commit comments