Skeleton go pew pew

Also zombie go boom
This commit is contained in:
2024-07-29 23:32:42 +02:00
parent 8d00672806
commit 653171cbb2
17 changed files with 623 additions and 139 deletions

View File

@@ -0,0 +1,107 @@
package systems.brn.plasticgun.mixins;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.ai.goal.BowAttackGoal;
import net.minecraft.entity.ai.goal.GoalSelector;
import net.minecraft.entity.ai.goal.MeleeAttackGoal;
import net.minecraft.entity.mob.AbstractSkeletonEntity;
import net.minecraft.entity.projectile.ProjectileUtil;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.item.RangedWeaponItem;
import net.minecraft.util.Hand;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.Difficulty;
import net.minecraft.world.LocalDifficulty;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import systems.brn.plasticgun.PlasticGun;
import systems.brn.plasticgun.guns.Gun;
import systems.brn.plasticgun.guns.WeaponShootGoal;
import static systems.brn.plasticgun.PlasticGun.guns;
import static systems.brn.plasticgun.PlasticGun.itemGunMap;
import static systems.brn.plasticgun.lib.Util.getDifficultyAdjustedChance;
@Mixin(AbstractSkeletonEntity.class)
public class AbstractSkeletonEntityGunMixin {
@Unique
protected boolean isHoldingGun() {
AbstractSkeletonEntity thisObject = (AbstractSkeletonEntity) (Object) this;
ItemStack mainHandStack = thisObject.getMainHandStack();
ItemStack offhandHandStack = thisObject.getOffHandStack();
return itemGunMap.containsKey(mainHandStack.getItem()) || itemGunMap.containsKey(offhandHandStack.getItem());
}
@Inject(method = "canUseRangedWeapon", at = @At("HEAD"), cancellable = true)
public void canUseRangedWeapon(RangedWeaponItem weapon, CallbackInfoReturnable<Boolean> cir) {
cir.setReturnValue(weapon == Items.BOW || itemGunMap.containsKey(weapon));
}
@Inject(method = "updateAttackType", at = @At("HEAD"), cancellable = true)
public void updateAttackType(CallbackInfo ci) {
AbstractSkeletonEntity thisObject = (AbstractSkeletonEntity) (Object) this;
// Remove existing attack goals
thisObject.goalSelector.remove(thisObject.bowAttackGoal);
thisObject.goalSelector.remove(thisObject.meleeAttackGoal);
// Add WeaponShootGoal if holding a gun
if (isHoldingGun()) {
thisObject.goalSelector.add(4, new WeaponShootGoal<>(thisObject, 1.0, 15.0F));
} else {
// Keep existing logic for bows
ItemStack itemStack = thisObject.getStackInHand(ProjectileUtil.getHandPossiblyHolding(thisObject, Items.BOW));
if (itemStack.isOf(Items.BOW)) {
int attackInterval = thisObject.getWorld().getDifficulty() == Difficulty.HARD ? 20 : 40;
BowAttackGoal<AbstractSkeletonEntity> bowAttackGoal = new BowAttackGoal<>(thisObject, 1.0, attackInterval, 15.0F);
thisObject.goalSelector.add(4, bowAttackGoal);
} else {
// Default to melee attack if no bow
MeleeAttackGoal meleeAttackGoal = new MeleeAttackGoal(thisObject, 1.2, false) {
@Override
public void stop() {
super.stop();
thisObject.setAttacking(false);
}
@Override
public void start() {
super.start();
thisObject.setAttacking(true);
}
};
thisObject.goalSelector.add(4, meleeAttackGoal);
}
}
ci.cancel();
}
@Inject(method = "initEquipment", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/mob/AbstractSkeletonEntity;equipStack(Lnet/minecraft/entity/EquipmentSlot;Lnet/minecraft/item/ItemStack;)V"), cancellable = true)
protected void initEquipment(Random random, LocalDifficulty localDifficulty, CallbackInfo ci) {
AbstractSkeletonEntity thisObject = (AbstractSkeletonEntity) (Object) this;
// Get world difficulty
World world = thisObject.getWorld();
int difficultyAdjustedChance = getDifficultyAdjustedChance(localDifficulty, world);
// Equip item based on adjusted chance
if (random.nextInt(difficultyAdjustedChance) == 0) {
thisObject.equipStack(EquipmentSlot.MAINHAND, new ItemStack(guns.get(random.nextInt(guns.size()))));
} else {
thisObject.equipStack(EquipmentSlot.MAINHAND, new ItemStack(Items.BOW));
}
ci.cancel();
}
}

View File

@@ -0,0 +1,83 @@
package systems.brn.plasticgun.mixins;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.entity.mob.ZombieEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.Difficulty;
import net.minecraft.world.LocalDifficulty;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import systems.brn.plasticgun.PlasticGun;
import systems.brn.plasticgun.grenades.GrenadeItem;
import java.util.Arrays;
import static systems.brn.plasticgun.PlasticGun.grenades;
import static systems.brn.plasticgun.lib.Util.getDifficultyAdjustedChance;
import static systems.brn.plasticgun.lib.Util.selectWeaponIndex;
@Mixin(ZombieEntity.class)
public abstract class ZombieGrenadeMixin extends MobEntity {
@Shadow
public abstract void tick();
// Constructor required for the Mixin
protected ZombieGrenadeMixin(EntityType<? extends MobEntity> entityType, World world) {
super(entityType, world);
}
@Inject(method = "initEquipment", at = @At("HEAD"), cancellable = true)
protected void initEquipment(Random random, LocalDifficulty localDifficulty, CallbackInfo ci) {
super.initEquipment(random, localDifficulty);
World world = this.getWorld();
int difficultyAdjustedChance = getDifficultyAdjustedChance(localDifficulty, world);
// Equip item based on adjusted chance
if (random.nextInt(difficultyAdjustedChance) == 0) {
int i = random.nextInt(20);
ItemStack stackToEquip;
if (i < 8) {
stackToEquip = new ItemStack(Items.IRON_SWORD);
} else if (i < 14) {
int grenadeIndex = selectWeaponIndex(random, localDifficulty, grenades.size());
stackToEquip = new ItemStack(grenades.get(grenadeIndex));
Arrays.fill(this.handDropChances, 0F);
} else {
stackToEquip = new ItemStack(Items.IRON_SHOVEL);
}
this.equipStack(EquipmentSlot.MAINHAND, stackToEquip);
}
ci.cancel();
}
@Inject(method = "dropEquipment", at = @At("RETURN"))
protected void dropEquipment(ServerWorld world, DamageSource source, boolean causedByPlayer, CallbackInfo ci) {
ItemStack mainHandItem = this.getEquippedStack(EquipmentSlot.MAINHAND);
ItemStack offHandItem = this.getEquippedStack(EquipmentSlot.OFFHAND);
for (GrenadeItem grenadeItem : grenades) {
if (mainHandItem.getItem() == grenadeItem) {
grenadeItem.turnIntoEntity(this, mainHandItem, 0, grenadeItem.explosionTarget);
break;
}
if (offHandItem.getItem() == grenadeItem) {
grenadeItem.turnIntoEntity(this, offHandItem, 0, grenadeItem.explosionTarget);
break;
}
}
}
}