#how to add custom attack sounds and sweep particle to a weapon
39 messages · Page 1 of 1 (latest)
Did you ever figure it out?
Because I'm trying to do it as well and can't figure out how to do it
same
assuming latest mc version:
PlayerEnity#attack uses the SoundEvents.ENTITY_PLAYER_ATTACK_SWEEP sound and PlayerEntity#spawnSweepAttackParticles to spawn the sweep particles
Mixin to PlayerEntity
for the particles:
ModifyExpressionValue into PlayerEntity#spawnSweepAttackParticles
and at the FIELD targetting the ParticleTypes.SWEEP_ATTACK
for the sound:
ModifyExpressionValue into PlayerEntity#attack and at the FIELD targetting SoundEvents.ENTITY_PLAYER_ATTACK_SWEEP
Will that change the default sweep particle or add a new one that can be used by a specific item?
Sorry, haven't really meddled with mixin yet
ModifyExpressionValue provides you with the original thing you are modifying (in this case the particle type or the sweep sound event)
based on your own code, you either return the original (does not meet your condition for your own values), or you provide new values
lets say you want to modify the doThing method by changing the action provided to a method doAction. you can ModifyExpressionValue the getAction invoke, and the code ends up looking something like (overly simplified):
original:
public void doThing() {
doAction( getAction() );
}
mixin modified
public void doThing() {
// your annotation tells it to wrap the getAction call and change the result
doAction( getModifiedAction(getAction()) );
}
// this is the method in your mixin. its added to the target class
private Action getModifiedAction(Action original) {
if (!shouldChangeAction()) return original
return MY_CUSTOM_ACTION;
}
Would the mixin starts as :
public class PlayerEntityMixin extends PlayerEntity {
@ModifyExpressionValue()
}
?
(In this case it's for the sweep particles)
yep
I might ask for help again tomorrow, I didn't get further than that 😂
you would have 2 annotations
for the first:
ModifyExpressionValue into PlayerEntity#spawnSweepAttackParticles
and at the FIELD targetting the ParticleTypes.SWEEP_ATTACK
spawnSweepAttackParticles is the method
in the at, FIELD is the value, SWEEP_ATTACK is the target
you should let the minecraft development plugin autocomplete those for you
Ooooh it can do that ?
(this assumes your thing is in the right tag or is a SwordItem)
It is indeed a SwordItem
for the second
ModifyExpressionValue into PlayerEntity#attack and at the FIELD targetting SoundEvents.ENTITY_PLAYER_ATTACK_SWEEP
attack is the method
in the at, FIELD is the value, ENTITY_PLAYER_ATTACK_SWEEP is the target
And so I would need an if statement in the mixin to choose which sweep attack gets called?
Or is that done another way?
Alright, will try that tomorrow !
(And probably come back with more questions xD)
Thanks for your kind help !
i tried something but it didnt work:
private void injectSpawnSweepAttackParticles(CallbackInfo info) {
PlayerEntity player = (PlayerEntity) (Object) this;
if (player.getMainHandStack() == ModItems.AETHERIAL_BLADE.getDefaultStack()) {
double d = (double) (-MathHelper.sin(player.getYaw() * 0.017453292F));
double e = (double) MathHelper.cos(player.getYaw() * 0.017453292F);
if (player.getWorld() instanceof ServerWorld) {
((ServerWorld) player.getWorld()).spawnParticles(ParticleTypes.ANGRY_VILLAGER, player.getX() + d, player.getBodyY(0.5), player.getZ() + e, 0, d, 0.0, e, 0.0);
}
}
}```
ModifyExpressionValue not inject
@Mixin(PlayerEntity.class)
public abstract class PlayerEntityMixin extends LivingEntity {
@ModifyExpressionValue(method="", at=@At(value="", target=""))
private ReturnTypeHere myMethod(ReturnTypeHere original) {
// My Checks Here and conditional return
return original;
}
}
(it will ask for a constructor but mixin will ignore the constructor, let the IDE make a default one, thats fine)
i figured it out
private void injectSpawnSweepAttackParticles(CallbackInfo info) {
PlayerEntity player = (PlayerEntity) (Object) this;
if (player.getMainHandStack().isOf(ModItems.AETHERIAL_BLADE)) {
double d = (double) (-MathHelper.sin(player.getYaw() * 0.017453292F));
double e = (double) MathHelper.cos(player.getYaw() * 0.017453292F);
if (player.getWorld() instanceof ServerWorld) {
((ServerWorld) player.getWorld()).spawnParticles(ParticleTypes.ANGRY_VILLAGER, player.getX() + d, player.getBodyY(0.5), player.getZ() + e, 0, d, 0.0, e, 0.0);
}
info.cancel();
}
}```
just keep in mind that any other mod that spawns sweep particles without requiring a stack check could be broken by your mixin
(silently, it just wont work because you return from the method early)
what would the return type be in this case?
public abstract class PlayerEntityMixin extends LivingEntity {
protected PlayerEntityMixin(EntityType<? extends LivingEntity> entityType, World world) {
super(entityType, world);
}
@ModifyExpressionValue(method="spawnSweepAttackParticles", at=@At(value="FIELD", target="ENTITY_PLAYER_ATTACK_SWEEP "))
private void spawnSweepAttackHoelyBeheader(void original) {
PlayerEntity player = (PlayerEntity) (Object) this;
if (player.getMainHandStack().isOf(ModItems.HOELY_BEHEADER)) {
double d = (double) (-MathHelper.sin(this.getYaw() * ((float) Math.PI / 180F)));
double e = (double) MathHelper.cos(this.getYaw() * ((float) Math.PI / 180F));
if (this.getWorld() instanceof ServerWorld) {
((ServerWorld) this.getWorld()).spawnParticles(ModParticles.HOELY_BEHEADER_SWEEP_ATTACK_PARTICLE,
this.getX() + d, this.getBodyY((double) 0.5F), this.getZ() + e, 0, d, (double) 0.0F, e, (double) 0.0F);
}
return original;
}
}
}```
thats fire
thank you :)